extzstd 0.2 → 0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/HISTORY.ja.md +13 -0
- data/README.md +17 -14
- data/contrib/zstd/{NEWS → CHANGELOG} +115 -2
- data/contrib/zstd/CODE_OF_CONDUCT.md +5 -0
- data/contrib/zstd/Makefile +99 -53
- data/contrib/zstd/README.md +59 -39
- data/contrib/zstd/TESTING.md +1 -1
- data/contrib/zstd/appveyor.yml +17 -6
- data/contrib/zstd/lib/BUCK +29 -2
- data/contrib/zstd/lib/Makefile +118 -21
- data/contrib/zstd/lib/README.md +84 -44
- data/contrib/zstd/lib/common/bitstream.h +17 -33
- data/contrib/zstd/lib/common/compiler.h +62 -8
- data/contrib/zstd/lib/common/cpu.h +215 -0
- data/contrib/zstd/lib/common/debug.c +44 -0
- data/contrib/zstd/lib/common/debug.h +134 -0
- data/contrib/zstd/lib/common/entropy_common.c +16 -1
- data/contrib/zstd/lib/common/error_private.c +7 -0
- data/contrib/zstd/lib/common/fse.h +48 -44
- data/contrib/zstd/lib/common/fse_decompress.c +3 -3
- data/contrib/zstd/lib/common/huf.h +169 -113
- data/contrib/zstd/lib/common/mem.h +20 -2
- data/contrib/zstd/lib/common/pool.c +135 -49
- data/contrib/zstd/lib/common/pool.h +40 -21
- data/contrib/zstd/lib/common/threading.c +2 -2
- data/contrib/zstd/lib/common/threading.h +12 -12
- data/contrib/zstd/lib/common/xxhash.c +3 -2
- data/contrib/zstd/lib/common/zstd_common.c +3 -6
- data/contrib/zstd/lib/common/zstd_errors.h +17 -7
- data/contrib/zstd/lib/common/zstd_internal.h +76 -48
- data/contrib/zstd/lib/compress/fse_compress.c +89 -209
- data/contrib/zstd/lib/compress/hist.c +203 -0
- data/contrib/zstd/lib/compress/hist.h +95 -0
- data/contrib/zstd/lib/compress/huf_compress.c +188 -80
- data/contrib/zstd/lib/compress/zstd_compress.c +2500 -1203
- data/contrib/zstd/lib/compress/zstd_compress_internal.h +463 -62
- data/contrib/zstd/lib/compress/zstd_double_fast.c +321 -131
- data/contrib/zstd/lib/compress/zstd_double_fast.h +13 -4
- data/contrib/zstd/lib/compress/zstd_fast.c +335 -108
- data/contrib/zstd/lib/compress/zstd_fast.h +12 -6
- data/contrib/zstd/lib/compress/zstd_lazy.c +654 -313
- data/contrib/zstd/lib/compress/zstd_lazy.h +44 -16
- data/contrib/zstd/lib/compress/zstd_ldm.c +310 -420
- data/contrib/zstd/lib/compress/zstd_ldm.h +63 -26
- data/contrib/zstd/lib/compress/zstd_opt.c +773 -325
- data/contrib/zstd/lib/compress/zstd_opt.h +31 -5
- data/contrib/zstd/lib/compress/zstdmt_compress.c +1468 -518
- data/contrib/zstd/lib/compress/zstdmt_compress.h +96 -45
- data/contrib/zstd/lib/decompress/huf_decompress.c +518 -282
- data/contrib/zstd/lib/decompress/zstd_ddict.c +240 -0
- data/contrib/zstd/lib/decompress/zstd_ddict.h +44 -0
- data/contrib/zstd/lib/decompress/zstd_decompress.c +613 -1513
- data/contrib/zstd/lib/decompress/zstd_decompress_block.c +1311 -0
- data/contrib/zstd/lib/decompress/zstd_decompress_block.h +59 -0
- data/contrib/zstd/lib/decompress/zstd_decompress_internal.h +175 -0
- data/contrib/zstd/lib/dictBuilder/cover.c +194 -113
- data/contrib/zstd/lib/dictBuilder/cover.h +112 -0
- data/contrib/zstd/lib/dictBuilder/divsufsort.c +3 -3
- data/contrib/zstd/lib/dictBuilder/fastcover.c +740 -0
- data/contrib/zstd/lib/dictBuilder/zdict.c +142 -106
- data/contrib/zstd/lib/dictBuilder/zdict.h +115 -49
- data/contrib/zstd/lib/legacy/zstd_legacy.h +44 -12
- data/contrib/zstd/lib/legacy/zstd_v01.c +41 -10
- data/contrib/zstd/lib/legacy/zstd_v01.h +12 -7
- data/contrib/zstd/lib/legacy/zstd_v02.c +37 -12
- data/contrib/zstd/lib/legacy/zstd_v02.h +12 -7
- data/contrib/zstd/lib/legacy/zstd_v03.c +38 -12
- data/contrib/zstd/lib/legacy/zstd_v03.h +12 -7
- data/contrib/zstd/lib/legacy/zstd_v04.c +55 -174
- data/contrib/zstd/lib/legacy/zstd_v04.h +12 -7
- data/contrib/zstd/lib/legacy/zstd_v05.c +59 -31
- data/contrib/zstd/lib/legacy/zstd_v05.h +12 -7
- data/contrib/zstd/lib/legacy/zstd_v06.c +48 -20
- data/contrib/zstd/lib/legacy/zstd_v06.h +10 -5
- data/contrib/zstd/lib/legacy/zstd_v07.c +62 -29
- data/contrib/zstd/lib/legacy/zstd_v07.h +10 -5
- data/contrib/zstd/lib/zstd.h +1346 -832
- data/ext/extzstd.c +27 -19
- data/ext/extzstd_stream.c +20 -4
- data/ext/zstd_compress.c +1 -0
- data/ext/zstd_decompress.c +4 -0
- data/ext/zstd_dictbuilder.c +4 -0
- data/ext/zstd_dictbuilder_fastcover.c +5 -0
- data/lib/extzstd.rb +52 -220
- data/lib/extzstd/version.rb +1 -1
- metadata +21 -7
- data/contrib/zstd/circle.yml +0 -63
|
@@ -39,6 +39,10 @@ extern "C" {
|
|
|
39
39
|
# define MEM_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */
|
|
40
40
|
#endif
|
|
41
41
|
|
|
42
|
+
#ifndef __has_builtin
|
|
43
|
+
# define __has_builtin(x) 0 /* compat. with non-clang compilers */
|
|
44
|
+
#endif
|
|
45
|
+
|
|
42
46
|
/* code only tested on 32 and 64 bits systems */
|
|
43
47
|
#define MEM_STATIC_ASSERT(c) { enum { MEM_static_assert = 1/(int)(!!(c)) }; }
|
|
44
48
|
MEM_STATIC void MEM_check(void) { MEM_STATIC_ASSERT((sizeof(size_t)==4) || (sizeof(size_t)==8)); }
|
|
@@ -57,11 +61,23 @@ MEM_STATIC void MEM_check(void) { MEM_STATIC_ASSERT((sizeof(size_t)==4) || (size
|
|
|
57
61
|
typedef uint64_t U64;
|
|
58
62
|
typedef int64_t S64;
|
|
59
63
|
#else
|
|
64
|
+
# include <limits.h>
|
|
65
|
+
#if CHAR_BIT != 8
|
|
66
|
+
# error "this implementation requires char to be exactly 8-bit type"
|
|
67
|
+
#endif
|
|
60
68
|
typedef unsigned char BYTE;
|
|
69
|
+
#if USHRT_MAX != 65535
|
|
70
|
+
# error "this implementation requires short to be exactly 16-bit type"
|
|
71
|
+
#endif
|
|
61
72
|
typedef unsigned short U16;
|
|
62
73
|
typedef signed short S16;
|
|
74
|
+
#if UINT_MAX != 4294967295
|
|
75
|
+
# error "this implementation requires int to be exactly 32-bit type"
|
|
76
|
+
#endif
|
|
63
77
|
typedef unsigned int U32;
|
|
64
78
|
typedef signed int S32;
|
|
79
|
+
/* note : there are no limits defined for long long type in C90.
|
|
80
|
+
* limits exist in C99, however, in such case, <stdint.h> is preferred */
|
|
65
81
|
typedef unsigned long long U64;
|
|
66
82
|
typedef signed long long S64;
|
|
67
83
|
#endif
|
|
@@ -186,7 +202,8 @@ MEM_STATIC U32 MEM_swap32(U32 in)
|
|
|
186
202
|
{
|
|
187
203
|
#if defined(_MSC_VER) /* Visual Studio */
|
|
188
204
|
return _byteswap_ulong(in);
|
|
189
|
-
#elif defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)
|
|
205
|
+
#elif (defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)) \
|
|
206
|
+
|| (defined(__clang__) && __has_builtin(__builtin_bswap32))
|
|
190
207
|
return __builtin_bswap32(in);
|
|
191
208
|
#else
|
|
192
209
|
return ((in << 24) & 0xff000000 ) |
|
|
@@ -200,7 +217,8 @@ MEM_STATIC U64 MEM_swap64(U64 in)
|
|
|
200
217
|
{
|
|
201
218
|
#if defined(_MSC_VER) /* Visual Studio */
|
|
202
219
|
return _byteswap_uint64(in);
|
|
203
|
-
#elif defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)
|
|
220
|
+
#elif (defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)) \
|
|
221
|
+
|| (defined(__clang__) && __has_builtin(__builtin_bswap64))
|
|
204
222
|
return __builtin_bswap64(in);
|
|
205
223
|
#else
|
|
206
224
|
return ((in << 56) & 0xff00000000000000ULL) |
|
|
@@ -10,7 +10,9 @@
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
/* ====== Dependencies ======= */
|
|
13
|
-
#include <stddef.h>
|
|
13
|
+
#include <stddef.h> /* size_t */
|
|
14
|
+
#include "debug.h" /* assert */
|
|
15
|
+
#include "zstd_internal.h" /* ZSTD_malloc, ZSTD_free */
|
|
14
16
|
#include "pool.h"
|
|
15
17
|
|
|
16
18
|
/* ====== Compiler specifics ====== */
|
|
@@ -32,8 +34,9 @@ typedef struct POOL_job_s {
|
|
|
32
34
|
struct POOL_ctx_s {
|
|
33
35
|
ZSTD_customMem customMem;
|
|
34
36
|
/* Keep track of the threads */
|
|
35
|
-
ZSTD_pthread_t
|
|
36
|
-
size_t
|
|
37
|
+
ZSTD_pthread_t* threads;
|
|
38
|
+
size_t threadCapacity;
|
|
39
|
+
size_t threadLimit;
|
|
37
40
|
|
|
38
41
|
/* The queue is a circular buffer */
|
|
39
42
|
POOL_job *queue;
|
|
@@ -57,10 +60,10 @@ struct POOL_ctx_s {
|
|
|
57
60
|
};
|
|
58
61
|
|
|
59
62
|
/* POOL_thread() :
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
*/
|
|
63
|
+
* Work thread for the thread pool.
|
|
64
|
+
* Waits for jobs and executes them.
|
|
65
|
+
* @returns : NULL on failure else non-null.
|
|
66
|
+
*/
|
|
64
67
|
static void* POOL_thread(void* opaque) {
|
|
65
68
|
POOL_ctx* const ctx = (POOL_ctx*)opaque;
|
|
66
69
|
if (!ctx) { return NULL; }
|
|
@@ -68,50 +71,55 @@ static void* POOL_thread(void* opaque) {
|
|
|
68
71
|
/* Lock the mutex and wait for a non-empty queue or until shutdown */
|
|
69
72
|
ZSTD_pthread_mutex_lock(&ctx->queueMutex);
|
|
70
73
|
|
|
71
|
-
while (ctx->queueEmpty
|
|
74
|
+
while ( ctx->queueEmpty
|
|
75
|
+
|| (ctx->numThreadsBusy >= ctx->threadLimit) ) {
|
|
76
|
+
if (ctx->shutdown) {
|
|
77
|
+
/* even if !queueEmpty, (possible if numThreadsBusy >= threadLimit),
|
|
78
|
+
* a few threads will be shutdown while !queueEmpty,
|
|
79
|
+
* but enough threads will remain active to finish the queue */
|
|
80
|
+
ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
|
|
81
|
+
return opaque;
|
|
82
|
+
}
|
|
72
83
|
ZSTD_pthread_cond_wait(&ctx->queuePopCond, &ctx->queueMutex);
|
|
73
84
|
}
|
|
74
|
-
/* empty => shutting down: so stop */
|
|
75
|
-
if (ctx->queueEmpty) {
|
|
76
|
-
ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
|
|
77
|
-
return opaque;
|
|
78
|
-
}
|
|
79
85
|
/* Pop a job off the queue */
|
|
80
86
|
{ POOL_job const job = ctx->queue[ctx->queueHead];
|
|
81
87
|
ctx->queueHead = (ctx->queueHead + 1) % ctx->queueSize;
|
|
82
88
|
ctx->numThreadsBusy++;
|
|
83
89
|
ctx->queueEmpty = ctx->queueHead == ctx->queueTail;
|
|
84
90
|
/* Unlock the mutex, signal a pusher, and run the job */
|
|
85
|
-
ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
|
|
86
91
|
ZSTD_pthread_cond_signal(&ctx->queuePushCond);
|
|
92
|
+
ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
|
|
87
93
|
|
|
88
94
|
job.function(job.opaque);
|
|
89
95
|
|
|
90
96
|
/* If the intended queue size was 0, signal after finishing job */
|
|
97
|
+
ZSTD_pthread_mutex_lock(&ctx->queueMutex);
|
|
98
|
+
ctx->numThreadsBusy--;
|
|
91
99
|
if (ctx->queueSize == 1) {
|
|
92
|
-
ZSTD_pthread_mutex_lock(&ctx->queueMutex);
|
|
93
|
-
ctx->numThreadsBusy--;
|
|
94
|
-
ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
|
|
95
100
|
ZSTD_pthread_cond_signal(&ctx->queuePushCond);
|
|
96
|
-
|
|
101
|
+
}
|
|
102
|
+
ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
|
|
103
|
+
}
|
|
97
104
|
} /* for (;;) */
|
|
98
|
-
/* Unreachable */
|
|
105
|
+
assert(0); /* Unreachable */
|
|
99
106
|
}
|
|
100
107
|
|
|
101
108
|
POOL_ctx* POOL_create(size_t numThreads, size_t queueSize) {
|
|
102
109
|
return POOL_create_advanced(numThreads, queueSize, ZSTD_defaultCMem);
|
|
103
110
|
}
|
|
104
111
|
|
|
105
|
-
POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize,
|
|
112
|
+
POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize,
|
|
113
|
+
ZSTD_customMem customMem) {
|
|
106
114
|
POOL_ctx* ctx;
|
|
107
|
-
/* Check
|
|
115
|
+
/* Check parameters */
|
|
108
116
|
if (!numThreads) { return NULL; }
|
|
109
117
|
/* Allocate the context and zero initialize */
|
|
110
118
|
ctx = (POOL_ctx*)ZSTD_calloc(sizeof(POOL_ctx), customMem);
|
|
111
119
|
if (!ctx) { return NULL; }
|
|
112
120
|
/* Initialize the job queue.
|
|
113
|
-
* It needs one extra space since one space is wasted to differentiate
|
|
114
|
-
* and full queues.
|
|
121
|
+
* It needs one extra space since one space is wasted to differentiate
|
|
122
|
+
* empty and full queues.
|
|
115
123
|
*/
|
|
116
124
|
ctx->queueSize = queueSize + 1;
|
|
117
125
|
ctx->queue = (POOL_job*)ZSTD_malloc(ctx->queueSize * sizeof(POOL_job), customMem);
|
|
@@ -125,7 +133,7 @@ POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize, ZSTD_customM
|
|
|
125
133
|
ctx->shutdown = 0;
|
|
126
134
|
/* Allocate space for the thread handles */
|
|
127
135
|
ctx->threads = (ZSTD_pthread_t*)ZSTD_malloc(numThreads * sizeof(ZSTD_pthread_t), customMem);
|
|
128
|
-
ctx->
|
|
136
|
+
ctx->threadCapacity = 0;
|
|
129
137
|
ctx->customMem = customMem;
|
|
130
138
|
/* Check for errors */
|
|
131
139
|
if (!ctx->threads || !ctx->queue) { POOL_free(ctx); return NULL; }
|
|
@@ -133,11 +141,12 @@ POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize, ZSTD_customM
|
|
|
133
141
|
{ size_t i;
|
|
134
142
|
for (i = 0; i < numThreads; ++i) {
|
|
135
143
|
if (ZSTD_pthread_create(&ctx->threads[i], NULL, &POOL_thread, ctx)) {
|
|
136
|
-
ctx->
|
|
144
|
+
ctx->threadCapacity = i;
|
|
137
145
|
POOL_free(ctx);
|
|
138
146
|
return NULL;
|
|
139
147
|
} }
|
|
140
|
-
ctx->
|
|
148
|
+
ctx->threadCapacity = numThreads;
|
|
149
|
+
ctx->threadLimit = numThreads;
|
|
141
150
|
}
|
|
142
151
|
return ctx;
|
|
143
152
|
}
|
|
@@ -155,8 +164,8 @@ static void POOL_join(POOL_ctx* ctx) {
|
|
|
155
164
|
ZSTD_pthread_cond_broadcast(&ctx->queuePopCond);
|
|
156
165
|
/* Join all of the threads */
|
|
157
166
|
{ size_t i;
|
|
158
|
-
for (i = 0; i < ctx->
|
|
159
|
-
ZSTD_pthread_join(ctx->threads[i], NULL);
|
|
167
|
+
for (i = 0; i < ctx->threadCapacity; ++i) {
|
|
168
|
+
ZSTD_pthread_join(ctx->threads[i], NULL); /* note : could fail */
|
|
160
169
|
} }
|
|
161
170
|
}
|
|
162
171
|
|
|
@@ -171,54 +180,120 @@ void POOL_free(POOL_ctx *ctx) {
|
|
|
171
180
|
ZSTD_free(ctx, ctx->customMem);
|
|
172
181
|
}
|
|
173
182
|
|
|
183
|
+
|
|
184
|
+
|
|
174
185
|
size_t POOL_sizeof(POOL_ctx *ctx) {
|
|
175
186
|
if (ctx==NULL) return 0; /* supports sizeof NULL */
|
|
176
187
|
return sizeof(*ctx)
|
|
177
188
|
+ ctx->queueSize * sizeof(POOL_job)
|
|
178
|
-
+ ctx->
|
|
189
|
+
+ ctx->threadCapacity * sizeof(ZSTD_pthread_t);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
/* @return : 0 on success, 1 on error */
|
|
194
|
+
static int POOL_resize_internal(POOL_ctx* ctx, size_t numThreads)
|
|
195
|
+
{
|
|
196
|
+
if (numThreads <= ctx->threadCapacity) {
|
|
197
|
+
if (!numThreads) return 1;
|
|
198
|
+
ctx->threadLimit = numThreads;
|
|
199
|
+
return 0;
|
|
200
|
+
}
|
|
201
|
+
/* numThreads > threadCapacity */
|
|
202
|
+
{ ZSTD_pthread_t* const threadPool = (ZSTD_pthread_t*)ZSTD_malloc(numThreads * sizeof(ZSTD_pthread_t), ctx->customMem);
|
|
203
|
+
if (!threadPool) return 1;
|
|
204
|
+
/* replace existing thread pool */
|
|
205
|
+
memcpy(threadPool, ctx->threads, ctx->threadCapacity * sizeof(*threadPool));
|
|
206
|
+
ZSTD_free(ctx->threads, ctx->customMem);
|
|
207
|
+
ctx->threads = threadPool;
|
|
208
|
+
/* Initialize additional threads */
|
|
209
|
+
{ size_t threadId;
|
|
210
|
+
for (threadId = ctx->threadCapacity; threadId < numThreads; ++threadId) {
|
|
211
|
+
if (ZSTD_pthread_create(&threadPool[threadId], NULL, &POOL_thread, ctx)) {
|
|
212
|
+
ctx->threadCapacity = threadId;
|
|
213
|
+
return 1;
|
|
214
|
+
} }
|
|
215
|
+
} }
|
|
216
|
+
/* successfully expanded */
|
|
217
|
+
ctx->threadCapacity = numThreads;
|
|
218
|
+
ctx->threadLimit = numThreads;
|
|
219
|
+
return 0;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/* @return : 0 on success, 1 on error */
|
|
223
|
+
int POOL_resize(POOL_ctx* ctx, size_t numThreads)
|
|
224
|
+
{
|
|
225
|
+
int result;
|
|
226
|
+
if (ctx==NULL) return 1;
|
|
227
|
+
ZSTD_pthread_mutex_lock(&ctx->queueMutex);
|
|
228
|
+
result = POOL_resize_internal(ctx, numThreads);
|
|
229
|
+
ZSTD_pthread_cond_broadcast(&ctx->queuePopCond);
|
|
230
|
+
ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
|
|
231
|
+
return result;
|
|
179
232
|
}
|
|
180
233
|
|
|
181
234
|
/**
|
|
182
235
|
* Returns 1 if the queue is full and 0 otherwise.
|
|
183
236
|
*
|
|
184
|
-
*
|
|
185
|
-
* then a queue is empty if there is a thread free
|
|
237
|
+
* When queueSize is 1 (pool was created with an intended queueSize of 0),
|
|
238
|
+
* then a queue is empty if there is a thread free _and_ no job is waiting.
|
|
186
239
|
*/
|
|
187
240
|
static int isQueueFull(POOL_ctx const* ctx) {
|
|
188
241
|
if (ctx->queueSize > 1) {
|
|
189
242
|
return ctx->queueHead == ((ctx->queueTail + 1) % ctx->queueSize);
|
|
190
243
|
} else {
|
|
191
|
-
return ctx->numThreadsBusy == ctx->
|
|
244
|
+
return (ctx->numThreadsBusy == ctx->threadLimit) ||
|
|
192
245
|
!ctx->queueEmpty;
|
|
193
246
|
}
|
|
194
247
|
}
|
|
195
248
|
|
|
196
|
-
void POOL_add(void* ctxVoid, POOL_function function, void *opaque) {
|
|
197
|
-
POOL_ctx* const ctx = (POOL_ctx*)ctxVoid;
|
|
198
|
-
if (!ctx) { return; }
|
|
199
249
|
|
|
250
|
+
static void POOL_add_internal(POOL_ctx* ctx, POOL_function function, void *opaque)
|
|
251
|
+
{
|
|
252
|
+
POOL_job const job = {function, opaque};
|
|
253
|
+
assert(ctx != NULL);
|
|
254
|
+
if (ctx->shutdown) return;
|
|
255
|
+
|
|
256
|
+
ctx->queueEmpty = 0;
|
|
257
|
+
ctx->queue[ctx->queueTail] = job;
|
|
258
|
+
ctx->queueTail = (ctx->queueTail + 1) % ctx->queueSize;
|
|
259
|
+
ZSTD_pthread_cond_signal(&ctx->queuePopCond);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
void POOL_add(POOL_ctx* ctx, POOL_function function, void* opaque)
|
|
263
|
+
{
|
|
264
|
+
assert(ctx != NULL);
|
|
200
265
|
ZSTD_pthread_mutex_lock(&ctx->queueMutex);
|
|
201
|
-
|
|
266
|
+
/* Wait until there is space in the queue for the new job */
|
|
267
|
+
while (isQueueFull(ctx) && (!ctx->shutdown)) {
|
|
268
|
+
ZSTD_pthread_cond_wait(&ctx->queuePushCond, &ctx->queueMutex);
|
|
269
|
+
}
|
|
270
|
+
POOL_add_internal(ctx, function, opaque);
|
|
271
|
+
ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
|
|
272
|
+
}
|
|
202
273
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
ctx->queueTail = (ctx->queueTail + 1) % ctx->queueSize;
|
|
212
|
-
}
|
|
274
|
+
|
|
275
|
+
int POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque)
|
|
276
|
+
{
|
|
277
|
+
assert(ctx != NULL);
|
|
278
|
+
ZSTD_pthread_mutex_lock(&ctx->queueMutex);
|
|
279
|
+
if (isQueueFull(ctx)) {
|
|
280
|
+
ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
|
|
281
|
+
return 0;
|
|
213
282
|
}
|
|
283
|
+
POOL_add_internal(ctx, function, opaque);
|
|
214
284
|
ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
|
|
215
|
-
|
|
285
|
+
return 1;
|
|
216
286
|
}
|
|
217
287
|
|
|
288
|
+
|
|
218
289
|
#else /* ZSTD_MULTITHREAD not defined */
|
|
290
|
+
|
|
291
|
+
/* ========================== */
|
|
219
292
|
/* No multi-threading support */
|
|
293
|
+
/* ========================== */
|
|
294
|
+
|
|
220
295
|
|
|
221
|
-
/* We don't need any data, but if it is empty malloc() might return NULL. */
|
|
296
|
+
/* We don't need any data, but if it is empty, malloc() might return NULL. */
|
|
222
297
|
struct POOL_ctx_s {
|
|
223
298
|
int dummy;
|
|
224
299
|
};
|
|
@@ -240,9 +315,20 @@ void POOL_free(POOL_ctx* ctx) {
|
|
|
240
315
|
(void)ctx;
|
|
241
316
|
}
|
|
242
317
|
|
|
243
|
-
|
|
318
|
+
int POOL_resize(POOL_ctx* ctx, size_t numThreads) {
|
|
319
|
+
(void)ctx; (void)numThreads;
|
|
320
|
+
return 0;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
void POOL_add(POOL_ctx* ctx, POOL_function function, void* opaque) {
|
|
324
|
+
(void)ctx;
|
|
325
|
+
function(opaque);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
int POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque) {
|
|
244
329
|
(void)ctx;
|
|
245
330
|
function(opaque);
|
|
331
|
+
return 1;
|
|
246
332
|
}
|
|
247
333
|
|
|
248
334
|
size_t POOL_sizeof(POOL_ctx* ctx) {
|
|
@@ -17,7 +17,8 @@ extern "C" {
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
#include <stddef.h> /* size_t */
|
|
20
|
-
#
|
|
20
|
+
#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_customMem */
|
|
21
|
+
#include "zstd.h"
|
|
21
22
|
|
|
22
23
|
typedef struct POOL_ctx_s POOL_ctx;
|
|
23
24
|
|
|
@@ -27,35 +28,53 @@ typedef struct POOL_ctx_s POOL_ctx;
|
|
|
27
28
|
* The maximum number of queued jobs before blocking is `queueSize`.
|
|
28
29
|
* @return : POOL_ctx pointer on success, else NULL.
|
|
29
30
|
*/
|
|
30
|
-
POOL_ctx
|
|
31
|
+
POOL_ctx* POOL_create(size_t numThreads, size_t queueSize);
|
|
31
32
|
|
|
32
|
-
POOL_ctx
|
|
33
|
+
POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize,
|
|
34
|
+
ZSTD_customMem customMem);
|
|
33
35
|
|
|
34
36
|
/*! POOL_free() :
|
|
35
|
-
|
|
36
|
-
*/
|
|
37
|
-
void POOL_free(POOL_ctx
|
|
37
|
+
* Free a thread pool returned by POOL_create().
|
|
38
|
+
*/
|
|
39
|
+
void POOL_free(POOL_ctx* ctx);
|
|
40
|
+
|
|
41
|
+
/*! POOL_resize() :
|
|
42
|
+
* Expands or shrinks pool's number of threads.
|
|
43
|
+
* This is more efficient than releasing + creating a new context,
|
|
44
|
+
* since it tries to preserve and re-use existing threads.
|
|
45
|
+
* `numThreads` must be at least 1.
|
|
46
|
+
* @return : 0 when resize was successful,
|
|
47
|
+
* !0 (typically 1) if there is an error.
|
|
48
|
+
* note : only numThreads can be resized, queueSize remains unchanged.
|
|
49
|
+
*/
|
|
50
|
+
int POOL_resize(POOL_ctx* ctx, size_t numThreads);
|
|
38
51
|
|
|
39
52
|
/*! POOL_sizeof() :
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
53
|
+
* @return threadpool memory usage
|
|
54
|
+
* note : compatible with NULL (returns 0 in this case)
|
|
55
|
+
*/
|
|
56
|
+
size_t POOL_sizeof(POOL_ctx* ctx);
|
|
43
57
|
|
|
44
58
|
/*! POOL_function :
|
|
45
|
-
|
|
46
|
-
*/
|
|
47
|
-
typedef void (*POOL_function)(void
|
|
48
|
-
/*! POOL_add_function :
|
|
49
|
-
The function type for a generic thread pool add function.
|
|
50
|
-
*/
|
|
51
|
-
typedef void (*POOL_add_function)(void *, POOL_function, void *);
|
|
59
|
+
* The function type that can be added to a thread pool.
|
|
60
|
+
*/
|
|
61
|
+
typedef void (*POOL_function)(void*);
|
|
52
62
|
|
|
53
63
|
/*! POOL_add() :
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
64
|
+
* Add the job `function(opaque)` to the thread pool. `ctx` must be valid.
|
|
65
|
+
* Possibly blocks until there is room in the queue.
|
|
66
|
+
* Note : The function may be executed asynchronously,
|
|
67
|
+
* therefore, `opaque` must live until function has been completed.
|
|
68
|
+
*/
|
|
69
|
+
void POOL_add(POOL_ctx* ctx, POOL_function function, void* opaque);
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
/*! POOL_tryAdd() :
|
|
73
|
+
* Add the job `function(opaque)` to thread pool _if_ a worker is available.
|
|
74
|
+
* Returns immediately even if not (does not block).
|
|
75
|
+
* @return : 1 if successful, 0 if not.
|
|
76
|
+
*/
|
|
77
|
+
int POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque);
|
|
59
78
|
|
|
60
79
|
|
|
61
80
|
#if defined (__cplusplus)
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
* This file will hold wrapper for systems, which do not support pthreads
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
/* create fake symbol to avoid empty
|
|
18
|
-
int
|
|
17
|
+
/* create fake symbol to avoid empty translation unit warning */
|
|
18
|
+
int g_ZSTD_threading_useless_symbol;
|
|
19
19
|
|
|
20
20
|
#if defined(ZSTD_MULTITHREAD) && defined(_WIN32)
|
|
21
21
|
|