extlzham 0.0.1.PROTOTYPE

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.md +27 -0
  3. data/README.md +21 -0
  4. data/Rakefile +143 -0
  5. data/contrib/lzham/LICENSE +22 -0
  6. data/contrib/lzham/README.md +209 -0
  7. data/contrib/lzham/include/lzham.h +781 -0
  8. data/contrib/lzham/lzhamcomp/lzham_comp.h +38 -0
  9. data/contrib/lzham/lzhamcomp/lzham_lzbase.cpp +244 -0
  10. data/contrib/lzham/lzhamcomp/lzham_lzbase.h +45 -0
  11. data/contrib/lzham/lzhamcomp/lzham_lzcomp.cpp +608 -0
  12. data/contrib/lzham/lzhamcomp/lzham_lzcomp_internal.cpp +1966 -0
  13. data/contrib/lzham/lzhamcomp/lzham_lzcomp_internal.h +472 -0
  14. data/contrib/lzham/lzhamcomp/lzham_lzcomp_state.cpp +1413 -0
  15. data/contrib/lzham/lzhamcomp/lzham_match_accel.cpp +562 -0
  16. data/contrib/lzham/lzhamcomp/lzham_match_accel.h +146 -0
  17. data/contrib/lzham/lzhamcomp/lzham_null_threading.h +97 -0
  18. data/contrib/lzham/lzhamcomp/lzham_pthreads_threading.cpp +229 -0
  19. data/contrib/lzham/lzhamcomp/lzham_pthreads_threading.h +520 -0
  20. data/contrib/lzham/lzhamcomp/lzham_threading.h +12 -0
  21. data/contrib/lzham/lzhamcomp/lzham_win32_threading.cpp +220 -0
  22. data/contrib/lzham/lzhamcomp/lzham_win32_threading.h +368 -0
  23. data/contrib/lzham/lzhamdecomp/lzham_assert.cpp +66 -0
  24. data/contrib/lzham/lzhamdecomp/lzham_assert.h +40 -0
  25. data/contrib/lzham/lzhamdecomp/lzham_checksum.cpp +73 -0
  26. data/contrib/lzham/lzhamdecomp/lzham_checksum.h +13 -0
  27. data/contrib/lzham/lzhamdecomp/lzham_config.h +23 -0
  28. data/contrib/lzham/lzhamdecomp/lzham_core.h +264 -0
  29. data/contrib/lzham/lzhamdecomp/lzham_decomp.h +37 -0
  30. data/contrib/lzham/lzhamdecomp/lzham_helpers.h +54 -0
  31. data/contrib/lzham/lzhamdecomp/lzham_huffman_codes.cpp +262 -0
  32. data/contrib/lzham/lzhamdecomp/lzham_huffman_codes.h +14 -0
  33. data/contrib/lzham/lzhamdecomp/lzham_lzdecomp.cpp +1527 -0
  34. data/contrib/lzham/lzhamdecomp/lzham_lzdecompbase.cpp +131 -0
  35. data/contrib/lzham/lzhamdecomp/lzham_lzdecompbase.h +89 -0
  36. data/contrib/lzham/lzhamdecomp/lzham_math.h +142 -0
  37. data/contrib/lzham/lzhamdecomp/lzham_mem.cpp +284 -0
  38. data/contrib/lzham/lzhamdecomp/lzham_mem.h +112 -0
  39. data/contrib/lzham/lzhamdecomp/lzham_platform.cpp +157 -0
  40. data/contrib/lzham/lzhamdecomp/lzham_platform.h +284 -0
  41. data/contrib/lzham/lzhamdecomp/lzham_prefix_coding.cpp +351 -0
  42. data/contrib/lzham/lzhamdecomp/lzham_prefix_coding.h +146 -0
  43. data/contrib/lzham/lzhamdecomp/lzham_symbol_codec.cpp +1484 -0
  44. data/contrib/lzham/lzhamdecomp/lzham_symbol_codec.h +556 -0
  45. data/contrib/lzham/lzhamdecomp/lzham_timer.cpp +147 -0
  46. data/contrib/lzham/lzhamdecomp/lzham_timer.h +99 -0
  47. data/contrib/lzham/lzhamdecomp/lzham_traits.h +141 -0
  48. data/contrib/lzham/lzhamdecomp/lzham_types.h +97 -0
  49. data/contrib/lzham/lzhamdecomp/lzham_utils.h +58 -0
  50. data/contrib/lzham/lzhamdecomp/lzham_vector.cpp +75 -0
  51. data/contrib/lzham/lzhamdecomp/lzham_vector.h +588 -0
  52. data/contrib/lzham/lzhamlib/lzham_lib.cpp +179 -0
  53. data/examples/basic.rb +48 -0
  54. data/ext/extconf.rb +26 -0
  55. data/ext/extlzham.c +741 -0
  56. data/gemstub.rb +22 -0
  57. data/lib/extlzham/version.rb +5 -0
  58. data/lib/extlzham.rb +153 -0
  59. metadata +135 -0
@@ -0,0 +1,520 @@
1
+ // File: lzham_task_pool_pthreads.h
2
+ // See Copyright Notice and license at the end of include/lzham.h
3
+ #pragma once
4
+
5
+ #if LZHAM_USE_PTHREADS_API
6
+
7
+ #if LZHAM_NO_ATOMICS
8
+ #error No atomic operations defined in lzham_platform.h!
9
+ #endif
10
+
11
+ #ifdef __APPLE__
12
+ #include <libkern/OSAtomic.h>
13
+ #endif
14
+
15
+ #include <pthread.h>
16
+ #include <semaphore.h>
17
+ #include <unistd.h>
18
+ #include <sys/time.h>
19
+
20
+ #define LZHAM_RND_CONG(jcong) (69069U * jcong + 1234567U)
21
+
22
+ namespace lzham
23
+ {
24
+ // semaphore
25
+
26
+ #ifdef __APPLE__
27
+ class semaphore
28
+ {
29
+ LZHAM_NO_COPY_OR_ASSIGNMENT_OP(semaphore);
30
+
31
+ public:
32
+ inline semaphore(long initialCount, long maximumCount)
33
+ {
34
+ LZHAM_NOTE_UNUSED(maximumCount);
35
+ LZHAM_ASSERT(maximumCount >= initialCount);
36
+
37
+ for (uint tries = 0; tries < 16; tries++)
38
+ {
39
+ struct timeval tp;
40
+ struct timezone tzp;
41
+ gettimeofday(&tp, &tzp);
42
+ uint x = tp.tv_usec;
43
+
44
+ // Argh this stinks. Try to choose a name that won't conflict with anything the calling process uses.
45
+ for (uint i = 0; i < sizeof(m_name) - 1; i++)
46
+ {
47
+ x = LZHAM_RND_CONG(x);
48
+ char c = 'A' + (static_cast<uint8>(x ^ (x >> 20)) % 26);
49
+ m_name[i] = c;
50
+ }
51
+ m_name[sizeof(m_name) - 1] = '\0';
52
+
53
+ m_pSem = sem_open(m_name, O_CREAT | O_EXCL, S_IRWXU, initialCount);
54
+ if (m_pSem != SEM_FAILED)
55
+ break;
56
+ }
57
+
58
+ if (m_pSem == SEM_FAILED)
59
+ {
60
+ LZHAM_FAIL("semaphore: sem_init() failed");
61
+ }
62
+ }
63
+
64
+ inline ~semaphore()
65
+ {
66
+ sem_close(m_pSem);
67
+ sem_unlink(m_name);
68
+ }
69
+
70
+ inline void release(long releaseCount = 1)
71
+ {
72
+ LZHAM_ASSERT(releaseCount >= 1);
73
+
74
+ int status = 0;
75
+ #ifdef WIN32
76
+ if (1 == releaseCount)
77
+ status = sem_post(m_pSem);
78
+ else
79
+ status = sem_post_multiple(m_pSem, releaseCount);
80
+ #else
81
+ while (releaseCount > 0)
82
+ {
83
+ status = sem_post(m_pSem);
84
+ if (status)
85
+ break;
86
+ releaseCount--;
87
+ }
88
+ #endif
89
+
90
+ if (status)
91
+ {
92
+ LZHAM_FAIL("semaphore: sem_post() or sem_post_multiple() failed");
93
+ }
94
+ }
95
+
96
+ inline bool wait()
97
+ {
98
+ int status = sem_wait(m_pSem);
99
+
100
+ if (status)
101
+ {
102
+ if (errno != ETIMEDOUT)
103
+ {
104
+ LZHAM_FAIL("semaphore: sem_wait() or sem_timedwait() failed");
105
+ }
106
+ return false;
107
+ }
108
+
109
+ return true;
110
+ }
111
+
112
+ private:
113
+ sem_t *m_pSem;
114
+ char m_name[16];
115
+ };
116
+ #else
117
+ class semaphore
118
+ {
119
+ LZHAM_NO_COPY_OR_ASSIGNMENT_OP(semaphore);
120
+
121
+ public:
122
+ inline semaphore(long initialCount = 0, long maximumCount = 1, const char* pName = NULL)
123
+ {
124
+ LZHAM_NOTE_UNUSED(maximumCount), LZHAM_NOTE_UNUSED(pName);
125
+ LZHAM_ASSERT(maximumCount >= initialCount);
126
+ if (sem_init(&m_sem, 0, initialCount))
127
+ {
128
+ LZHAM_FAIL("semaphore: sem_init() failed");
129
+ }
130
+ }
131
+
132
+ inline ~semaphore()
133
+ {
134
+ sem_destroy(&m_sem);
135
+ }
136
+
137
+ inline void release(long releaseCount = 1)
138
+ {
139
+ LZHAM_ASSERT(releaseCount >= 1);
140
+
141
+ int status = 0;
142
+ #ifdef WIN32
143
+ if (1 == releaseCount)
144
+ status = sem_post(&m_sem);
145
+ else
146
+ status = sem_post_multiple(&m_sem, releaseCount);
147
+ #else
148
+ while (releaseCount > 0)
149
+ {
150
+ status = sem_post(&m_sem);
151
+ if (status)
152
+ break;
153
+ releaseCount--;
154
+ }
155
+ #endif
156
+
157
+ if (status)
158
+ {
159
+ LZHAM_FAIL("semaphore: sem_post() or sem_post_multiple() failed");
160
+ }
161
+ }
162
+
163
+ inline bool wait(uint32 milliseconds = UINT32_MAX)
164
+ {
165
+ int status;
166
+ if (milliseconds == UINT32_MAX)
167
+ {
168
+ status = sem_wait(&m_sem);
169
+ }
170
+ else
171
+ {
172
+ struct timespec interval;
173
+ interval.tv_sec = milliseconds / 1000;
174
+ interval.tv_nsec = (milliseconds % 1000) * 1000000L;
175
+ status = sem_timedwait(&m_sem, &interval);
176
+ }
177
+
178
+ if (status)
179
+ {
180
+ if (errno != ETIMEDOUT)
181
+ {
182
+ LZHAM_FAIL("semaphore: sem_wait() or sem_timedwait() failed");
183
+ }
184
+ return false;
185
+ }
186
+
187
+ return true;
188
+ }
189
+
190
+ private:
191
+ sem_t m_sem;
192
+ };
193
+ #endif
194
+
195
+ // spinlock
196
+
197
+ #ifdef __APPLE__
198
+ class spinlock
199
+ {
200
+ public:
201
+ inline spinlock() : m_lock(0)
202
+ {
203
+ }
204
+
205
+ inline ~spinlock()
206
+ {
207
+ }
208
+
209
+ inline void lock()
210
+ {
211
+ OSSpinLockLock(&m_lock);
212
+ }
213
+
214
+ inline void unlock()
215
+ {
216
+ OSSpinLockUnlock(&m_lock);
217
+ }
218
+
219
+ private:
220
+
221
+ OSSpinLock m_lock;
222
+ };
223
+ #else
224
+ class spinlock
225
+ {
226
+ public:
227
+ inline spinlock()
228
+ {
229
+ if (pthread_spin_init(&m_spinlock, 0))
230
+ {
231
+ LZHAM_FAIL("spinlock: pthread_spin_init() failed");
232
+ }
233
+ }
234
+
235
+ inline ~spinlock()
236
+ {
237
+ pthread_spin_destroy(&m_spinlock);
238
+ }
239
+
240
+ inline void lock()
241
+ {
242
+ if (pthread_spin_lock(&m_spinlock))
243
+ {
244
+ LZHAM_FAIL("spinlock: pthread_spin_lock() failed");
245
+ }
246
+ }
247
+
248
+ inline void unlock()
249
+ {
250
+ if (pthread_spin_unlock(&m_spinlock))
251
+ {
252
+ LZHAM_FAIL("spinlock: pthread_spin_unlock() failed");
253
+ }
254
+ }
255
+
256
+ private:
257
+ pthread_spinlock_t m_spinlock;
258
+ };
259
+ #endif // __APPLE__
260
+
261
+ // Thread safe stack
262
+
263
+ template<typename T, uint cMaxSize>
264
+ class tsstack
265
+ {
266
+ public:
267
+ inline tsstack() : m_top(0)
268
+ {
269
+ }
270
+
271
+ inline ~tsstack()
272
+ {
273
+ }
274
+
275
+ inline void clear()
276
+ {
277
+ m_spinlock.lock();
278
+ m_top = 0;
279
+ m_spinlock.unlock();
280
+ }
281
+
282
+ inline bool try_push(const T& obj)
283
+ {
284
+ bool result = false;
285
+ m_spinlock.lock();
286
+ if (m_top < (int)cMaxSize)
287
+ {
288
+ m_stack[m_top++] = obj;
289
+ result = true;
290
+ }
291
+ m_spinlock.unlock();
292
+ return result;
293
+ }
294
+
295
+ inline bool pop(T& obj)
296
+ {
297
+ bool result = false;
298
+ m_spinlock.lock();
299
+ if (m_top > 0)
300
+ {
301
+ obj = m_stack[--m_top];
302
+ result = true;
303
+ }
304
+ m_spinlock.unlock();
305
+ return result;
306
+ }
307
+
308
+ private:
309
+ spinlock m_spinlock;
310
+ T m_stack[cMaxSize];
311
+ int m_top;
312
+ };
313
+
314
+ // Simple task pool
315
+
316
+ class task_pool
317
+ {
318
+ public:
319
+ task_pool();
320
+ task_pool(uint num_threads);
321
+ ~task_pool();
322
+
323
+ enum { cMaxThreads = LZHAM_MAX_HELPER_THREADS };
324
+ bool init(uint num_threads);
325
+ void deinit();
326
+
327
+ inline uint get_num_threads() const { return m_num_threads; }
328
+ inline uint get_num_outstanding_tasks() const { return static_cast<uint>(m_num_outstanding_tasks); }
329
+
330
+ // C-style task callback
331
+ typedef void (*task_callback_func)(uint64 data, void* pData_ptr);
332
+ bool queue_task(task_callback_func pFunc, uint64 data = 0, void* pData_ptr = NULL);
333
+
334
+ class executable_task
335
+ {
336
+ public:
337
+ virtual void execute_task(uint64 data, void* pData_ptr) = 0;
338
+ };
339
+
340
+ // It's the caller's responsibility to delete pObj within the execute_task() method, if needed!
341
+ bool queue_task(executable_task* pObj, uint64 data = 0, void* pData_ptr = NULL);
342
+
343
+ template<typename S, typename T>
344
+ inline bool queue_object_task(S* pObject, T pObject_method, uint64 data = 0, void* pData_ptr = NULL);
345
+
346
+ template<typename S, typename T>
347
+ inline bool queue_multiple_object_tasks(S* pObject, T pObject_method, uint64 first_data, uint num_tasks, void* pData_ptr = NULL);
348
+
349
+ void join();
350
+
351
+ private:
352
+ struct task
353
+ {
354
+ inline task() : m_data(0), m_pData_ptr(NULL), m_pObj(NULL), m_flags(0) { }
355
+
356
+ uint64 m_data;
357
+ void* m_pData_ptr;
358
+
359
+ union
360
+ {
361
+ task_callback_func m_callback;
362
+ executable_task* m_pObj;
363
+ };
364
+
365
+ uint m_flags;
366
+ };
367
+
368
+ tsstack<task, cMaxThreads> m_task_stack;
369
+
370
+ uint m_num_threads;
371
+ pthread_t m_threads[cMaxThreads];
372
+
373
+ semaphore m_tasks_available;
374
+
375
+ enum task_flags
376
+ {
377
+ cTaskFlagObject = 1
378
+ };
379
+
380
+ volatile atomic32_t m_num_outstanding_tasks;
381
+ volatile atomic32_t m_exit_flag;
382
+
383
+ void process_task(task& tsk);
384
+
385
+ static void* thread_func(void *pContext);
386
+ };
387
+
388
+ enum object_task_flags
389
+ {
390
+ cObjectTaskFlagDefault = 0,
391
+ cObjectTaskFlagDeleteAfterExecution = 1
392
+ };
393
+
394
+ template<typename T>
395
+ class object_task : public task_pool::executable_task
396
+ {
397
+ public:
398
+ object_task(uint flags = cObjectTaskFlagDefault) :
399
+ m_pObject(NULL),
400
+ m_pMethod(NULL),
401
+ m_flags(flags)
402
+ {
403
+ }
404
+
405
+ typedef void (T::*object_method_ptr)(uint64 data, void* pData_ptr);
406
+
407
+ object_task(T* pObject, object_method_ptr pMethod, uint flags = cObjectTaskFlagDefault) :
408
+ m_pObject(pObject),
409
+ m_pMethod(pMethod),
410
+ m_flags(flags)
411
+ {
412
+ LZHAM_ASSERT(pObject && pMethod);
413
+ }
414
+
415
+ void init(T* pObject, object_method_ptr pMethod, uint flags = cObjectTaskFlagDefault)
416
+ {
417
+ LZHAM_ASSERT(pObject && pMethod);
418
+
419
+ m_pObject = pObject;
420
+ m_pMethod = pMethod;
421
+ m_flags = flags;
422
+ }
423
+
424
+ T* get_object() const { return m_pObject; }
425
+ object_method_ptr get_method() const { return m_pMethod; }
426
+
427
+ virtual void execute_task(uint64 data, void* pData_ptr)
428
+ {
429
+ (m_pObject->*m_pMethod)(data, pData_ptr);
430
+
431
+ if (m_flags & cObjectTaskFlagDeleteAfterExecution)
432
+ lzham_delete(this);
433
+ }
434
+
435
+ protected:
436
+ T* m_pObject;
437
+
438
+ object_method_ptr m_pMethod;
439
+
440
+ uint m_flags;
441
+ };
442
+
443
+ template<typename S, typename T>
444
+ inline bool task_pool::queue_object_task(S* pObject, T pObject_method, uint64 data, void* pData_ptr)
445
+ {
446
+ object_task<S> *pTask = lzham_new< object_task<S> >(pObject, pObject_method, cObjectTaskFlagDeleteAfterExecution);
447
+ if (!pTask)
448
+ return false;
449
+ return queue_task(pTask, data, pData_ptr);
450
+ }
451
+
452
+ template<typename S, typename T>
453
+ inline bool task_pool::queue_multiple_object_tasks(S* pObject, T pObject_method, uint64 first_data, uint num_tasks, void* pData_ptr)
454
+ {
455
+ LZHAM_ASSERT(m_num_threads);
456
+ LZHAM_ASSERT(pObject);
457
+ LZHAM_ASSERT(num_tasks);
458
+ if (!num_tasks)
459
+ return true;
460
+
461
+ bool status = true;
462
+
463
+ uint i;
464
+ for (i = 0; i < num_tasks; i++)
465
+ {
466
+ task tsk;
467
+
468
+ tsk.m_pObj = lzham_new< object_task<S> >(pObject, pObject_method, cObjectTaskFlagDeleteAfterExecution);
469
+ if (!tsk.m_pObj)
470
+ {
471
+ status = false;
472
+ break;
473
+ }
474
+
475
+ tsk.m_data = first_data + i;
476
+ tsk.m_pData_ptr = pData_ptr;
477
+ tsk.m_flags = cTaskFlagObject;
478
+
479
+ if (!m_task_stack.try_push(tsk))
480
+ {
481
+ status = false;
482
+ break;
483
+ }
484
+ }
485
+
486
+ if (i)
487
+ {
488
+ atomic_add32(&m_num_outstanding_tasks, i);
489
+
490
+ m_tasks_available.release(i);
491
+ }
492
+
493
+ return status;
494
+ }
495
+
496
+ // Sleep
497
+
498
+ inline void lzham_sleep(unsigned int milliseconds)
499
+ {
500
+ #ifdef WIN32
501
+ struct timespec interval;
502
+ interval.tv_sec = milliseconds / 1000;
503
+ interval.tv_nsec = (milliseconds % 1000) * 1000000L;
504
+ pthread_delay_np(&interval);
505
+ #else
506
+ while (milliseconds)
507
+ {
508
+ int msecs_to_sleep = LZHAM_MIN(milliseconds, 1000);
509
+ usleep(msecs_to_sleep * 1000);
510
+ milliseconds -= msecs_to_sleep;
511
+ }
512
+ #endif
513
+ }
514
+
515
+ // Returns number of helper threads we can add to the process on the current system (i.e. for a 4 CPU system this returns 3).
516
+ uint lzham_get_max_helper_threads();
517
+
518
+ } // namespace lzham
519
+
520
+ #endif // LZHAM_USE_PTHREADS_API
@@ -0,0 +1,12 @@
1
+ // File: lzham_threading.h
2
+ // See Copyright Notice and license at the end of include/lzham.h
3
+
4
+ #if LZHAM_USE_WIN32_API
5
+ #include "lzham_win32_threading.h"
6
+ #elif LZHAM_USE_PTHREADS_API
7
+ #include "lzham_pthreads_threading.h"
8
+ #else
9
+ #include "lzham_null_threading.h"
10
+ #endif
11
+
12
+