extlzham 0.0.1.PROTOTYPE3-x86-mingw32
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 +7 -0
- data/LICENSE.md +27 -0
- data/README.md +74 -0
- data/Rakefile +152 -0
- data/contrib/lzham/LICENSE +22 -0
- data/contrib/lzham/README.md +209 -0
- data/contrib/lzham/include/lzham.h +781 -0
- data/contrib/lzham/lzhamcomp/lzham_comp.h +38 -0
- data/contrib/lzham/lzhamcomp/lzham_lzbase.cpp +244 -0
- data/contrib/lzham/lzhamcomp/lzham_lzbase.h +45 -0
- data/contrib/lzham/lzhamcomp/lzham_lzcomp.cpp +608 -0
- data/contrib/lzham/lzhamcomp/lzham_lzcomp_internal.cpp +1966 -0
- data/contrib/lzham/lzhamcomp/lzham_lzcomp_internal.h +472 -0
- data/contrib/lzham/lzhamcomp/lzham_lzcomp_state.cpp +1413 -0
- data/contrib/lzham/lzhamcomp/lzham_match_accel.cpp +562 -0
- data/contrib/lzham/lzhamcomp/lzham_match_accel.h +146 -0
- data/contrib/lzham/lzhamcomp/lzham_null_threading.h +97 -0
- data/contrib/lzham/lzhamcomp/lzham_pthreads_threading.cpp +229 -0
- data/contrib/lzham/lzhamcomp/lzham_pthreads_threading.h +520 -0
- data/contrib/lzham/lzhamcomp/lzham_threading.h +12 -0
- data/contrib/lzham/lzhamcomp/lzham_win32_threading.cpp +220 -0
- data/contrib/lzham/lzhamcomp/lzham_win32_threading.h +368 -0
- data/contrib/lzham/lzhamdecomp/lzham_assert.cpp +66 -0
- data/contrib/lzham/lzhamdecomp/lzham_assert.h +40 -0
- data/contrib/lzham/lzhamdecomp/lzham_checksum.cpp +73 -0
- data/contrib/lzham/lzhamdecomp/lzham_checksum.h +13 -0
- data/contrib/lzham/lzhamdecomp/lzham_config.h +23 -0
- data/contrib/lzham/lzhamdecomp/lzham_core.h +264 -0
- data/contrib/lzham/lzhamdecomp/lzham_decomp.h +37 -0
- data/contrib/lzham/lzhamdecomp/lzham_helpers.h +54 -0
- data/contrib/lzham/lzhamdecomp/lzham_huffman_codes.cpp +262 -0
- data/contrib/lzham/lzhamdecomp/lzham_huffman_codes.h +14 -0
- data/contrib/lzham/lzhamdecomp/lzham_lzdecomp.cpp +1527 -0
- data/contrib/lzham/lzhamdecomp/lzham_lzdecompbase.cpp +131 -0
- data/contrib/lzham/lzhamdecomp/lzham_lzdecompbase.h +89 -0
- data/contrib/lzham/lzhamdecomp/lzham_math.h +142 -0
- data/contrib/lzham/lzhamdecomp/lzham_mem.cpp +284 -0
- data/contrib/lzham/lzhamdecomp/lzham_mem.h +112 -0
- data/contrib/lzham/lzhamdecomp/lzham_platform.cpp +157 -0
- data/contrib/lzham/lzhamdecomp/lzham_platform.h +284 -0
- data/contrib/lzham/lzhamdecomp/lzham_prefix_coding.cpp +351 -0
- data/contrib/lzham/lzhamdecomp/lzham_prefix_coding.h +146 -0
- data/contrib/lzham/lzhamdecomp/lzham_symbol_codec.cpp +1484 -0
- data/contrib/lzham/lzhamdecomp/lzham_symbol_codec.h +556 -0
- data/contrib/lzham/lzhamdecomp/lzham_timer.cpp +147 -0
- data/contrib/lzham/lzhamdecomp/lzham_timer.h +99 -0
- data/contrib/lzham/lzhamdecomp/lzham_traits.h +141 -0
- data/contrib/lzham/lzhamdecomp/lzham_types.h +97 -0
- data/contrib/lzham/lzhamdecomp/lzham_utils.h +58 -0
- data/contrib/lzham/lzhamdecomp/lzham_vector.cpp +75 -0
- data/contrib/lzham/lzhamdecomp/lzham_vector.h +588 -0
- data/contrib/lzham/lzhamlib/lzham_lib.cpp +179 -0
- data/examples/basic.rb +48 -0
- data/ext/constants.c +64 -0
- data/ext/decoder.c +313 -0
- data/ext/depend +5 -0
- data/ext/encoder.c +372 -0
- data/ext/error.c +80 -0
- data/ext/extconf.rb +29 -0
- data/ext/extlzham.c +34 -0
- data/ext/extlzham.h +62 -0
- data/gemstub.rb +22 -0
- data/lib/2.0/extlzham.so +0 -0
- data/lib/2.1/extlzham.so +0 -0
- data/lib/2.2/extlzham.so +0 -0
- data/lib/extlzham.rb +158 -0
- data/lib/extlzham/version.rb +5 -0
- data/test/test_extlzham.rb +35 -0
- metadata +156 -0
@@ -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
|
+
|
@@ -0,0 +1,220 @@
|
|
1
|
+
// File: lzham_task_pool_win32.cpp
|
2
|
+
// See Copyright Notice and license at the end of include/lzham.h
|
3
|
+
#include "lzham_core.h"
|
4
|
+
#include "lzham_win32_threading.h"
|
5
|
+
#include "lzham_timer.h"
|
6
|
+
#include <process.h>
|
7
|
+
|
8
|
+
#if LZHAM_USE_WIN32_API
|
9
|
+
|
10
|
+
namespace lzham
|
11
|
+
{
|
12
|
+
task_pool::task_pool() :
|
13
|
+
m_num_threads(0),
|
14
|
+
m_tasks_available(0, 32767),
|
15
|
+
m_num_outstanding_tasks(0),
|
16
|
+
m_exit_flag(false)
|
17
|
+
{
|
18
|
+
utils::zero_object(m_threads);
|
19
|
+
}
|
20
|
+
|
21
|
+
task_pool::task_pool(uint num_threads) :
|
22
|
+
m_num_threads(0),
|
23
|
+
m_tasks_available(0, 32767),
|
24
|
+
m_num_outstanding_tasks(0),
|
25
|
+
m_exit_flag(false)
|
26
|
+
{
|
27
|
+
utils::zero_object(m_threads);
|
28
|
+
|
29
|
+
bool status = init(num_threads);
|
30
|
+
LZHAM_VERIFY(status);
|
31
|
+
}
|
32
|
+
|
33
|
+
task_pool::~task_pool()
|
34
|
+
{
|
35
|
+
deinit();
|
36
|
+
}
|
37
|
+
|
38
|
+
bool task_pool::init(uint num_threads)
|
39
|
+
{
|
40
|
+
LZHAM_ASSERT(num_threads <= cMaxThreads);
|
41
|
+
num_threads = math::minimum<uint>(num_threads, cMaxThreads);
|
42
|
+
|
43
|
+
deinit();
|
44
|
+
|
45
|
+
bool succeeded = true;
|
46
|
+
|
47
|
+
m_num_threads = 0;
|
48
|
+
while (m_num_threads < num_threads)
|
49
|
+
{
|
50
|
+
m_threads[m_num_threads] = (HANDLE)_beginthreadex(NULL, 32768, thread_func, this, 0, NULL);
|
51
|
+
LZHAM_ASSERT(m_threads[m_num_threads] != 0);
|
52
|
+
|
53
|
+
if (!m_threads[m_num_threads])
|
54
|
+
{
|
55
|
+
succeeded = false;
|
56
|
+
break;
|
57
|
+
}
|
58
|
+
|
59
|
+
m_num_threads++;
|
60
|
+
}
|
61
|
+
|
62
|
+
if (!succeeded)
|
63
|
+
{
|
64
|
+
deinit();
|
65
|
+
return false;
|
66
|
+
}
|
67
|
+
|
68
|
+
return true;
|
69
|
+
}
|
70
|
+
|
71
|
+
void task_pool::deinit()
|
72
|
+
{
|
73
|
+
if (m_num_threads)
|
74
|
+
{
|
75
|
+
join();
|
76
|
+
|
77
|
+
atomic_exchange32(&m_exit_flag, true);
|
78
|
+
|
79
|
+
m_tasks_available.release(m_num_threads);
|
80
|
+
|
81
|
+
for (uint i = 0; i < m_num_threads; i++)
|
82
|
+
{
|
83
|
+
if (m_threads[i])
|
84
|
+
{
|
85
|
+
for ( ; ; )
|
86
|
+
{
|
87
|
+
DWORD result = WaitForSingleObject(m_threads[i], 30000);
|
88
|
+
if ((result == WAIT_OBJECT_0) || (result == WAIT_ABANDONED))
|
89
|
+
break;
|
90
|
+
}
|
91
|
+
|
92
|
+
CloseHandle(m_threads[i]);
|
93
|
+
m_threads[i] = NULL;
|
94
|
+
}
|
95
|
+
}
|
96
|
+
|
97
|
+
m_num_threads = 0;
|
98
|
+
|
99
|
+
atomic_exchange32(&m_exit_flag, false);
|
100
|
+
}
|
101
|
+
|
102
|
+
m_task_stack.clear();
|
103
|
+
m_num_outstanding_tasks = 0;
|
104
|
+
}
|
105
|
+
|
106
|
+
bool task_pool::queue_task(task_callback_func pFunc, uint64 data, void* pData_ptr)
|
107
|
+
{
|
108
|
+
LZHAM_ASSERT(m_num_threads);
|
109
|
+
LZHAM_ASSERT(pFunc);
|
110
|
+
|
111
|
+
task tsk;
|
112
|
+
tsk.m_callback = pFunc;
|
113
|
+
tsk.m_data = data;
|
114
|
+
tsk.m_pData_ptr = pData_ptr;
|
115
|
+
tsk.m_flags = 0;
|
116
|
+
|
117
|
+
if (!m_task_stack.try_push(tsk))
|
118
|
+
return false;
|
119
|
+
|
120
|
+
atomic_increment32(&m_num_outstanding_tasks);
|
121
|
+
|
122
|
+
m_tasks_available.release(1);
|
123
|
+
|
124
|
+
return true;
|
125
|
+
}
|
126
|
+
|
127
|
+
// It's the object's responsibility to delete pObj within the execute_task() method, if needed!
|
128
|
+
bool task_pool::queue_task(executable_task* pObj, uint64 data, void* pData_ptr)
|
129
|
+
{
|
130
|
+
LZHAM_ASSERT(m_num_threads);
|
131
|
+
LZHAM_ASSERT(pObj);
|
132
|
+
|
133
|
+
task tsk;
|
134
|
+
tsk.m_pObj = pObj;
|
135
|
+
tsk.m_data = data;
|
136
|
+
tsk.m_pData_ptr = pData_ptr;
|
137
|
+
tsk.m_flags = cTaskFlagObject;
|
138
|
+
|
139
|
+
if (!m_task_stack.try_push(tsk))
|
140
|
+
return false;
|
141
|
+
|
142
|
+
atomic_increment32(&m_num_outstanding_tasks);
|
143
|
+
|
144
|
+
m_tasks_available.release(1);
|
145
|
+
|
146
|
+
return true;
|
147
|
+
}
|
148
|
+
|
149
|
+
void task_pool::process_task(task& tsk)
|
150
|
+
{
|
151
|
+
if (tsk.m_flags & cTaskFlagObject)
|
152
|
+
tsk.m_pObj->execute_task(tsk.m_data, tsk.m_pData_ptr);
|
153
|
+
else
|
154
|
+
tsk.m_callback(tsk.m_data, tsk.m_pData_ptr);
|
155
|
+
|
156
|
+
atomic_decrement32(&m_num_outstanding_tasks);
|
157
|
+
}
|
158
|
+
|
159
|
+
void task_pool::join()
|
160
|
+
{
|
161
|
+
while (atomic_add32(&m_num_outstanding_tasks, 0) > 0)
|
162
|
+
{
|
163
|
+
task tsk;
|
164
|
+
if (m_task_stack.pop(tsk))
|
165
|
+
{
|
166
|
+
process_task(tsk);
|
167
|
+
}
|
168
|
+
else
|
169
|
+
{
|
170
|
+
lzham_sleep(1);
|
171
|
+
}
|
172
|
+
}
|
173
|
+
}
|
174
|
+
|
175
|
+
unsigned __stdcall task_pool::thread_func(void* pContext)
|
176
|
+
{
|
177
|
+
task_pool* pPool = static_cast<task_pool*>(pContext);
|
178
|
+
|
179
|
+
for ( ; ; )
|
180
|
+
{
|
181
|
+
if (!pPool->m_tasks_available.wait())
|
182
|
+
break;
|
183
|
+
|
184
|
+
if (pPool->m_exit_flag)
|
185
|
+
break;
|
186
|
+
|
187
|
+
task tsk;
|
188
|
+
if (pPool->m_task_stack.pop(tsk))
|
189
|
+
{
|
190
|
+
pPool->process_task(tsk);
|
191
|
+
}
|
192
|
+
}
|
193
|
+
|
194
|
+
_endthreadex(0);
|
195
|
+
return 0;
|
196
|
+
}
|
197
|
+
|
198
|
+
static uint g_num_processors;
|
199
|
+
|
200
|
+
uint lzham_get_max_helper_threads()
|
201
|
+
{
|
202
|
+
if (!g_num_processors)
|
203
|
+
{
|
204
|
+
SYSTEM_INFO system_info;
|
205
|
+
GetSystemInfo(&system_info);
|
206
|
+
g_num_processors = system_info.dwNumberOfProcessors;
|
207
|
+
}
|
208
|
+
|
209
|
+
if (g_num_processors > 1)
|
210
|
+
{
|
211
|
+
// use all CPU's
|
212
|
+
return LZHAM_MIN(task_pool::cMaxThreads, g_num_processors - 1);
|
213
|
+
}
|
214
|
+
|
215
|
+
return 0;
|
216
|
+
}
|
217
|
+
|
218
|
+
} // namespace lzham
|
219
|
+
|
220
|
+
#endif // LZHAM_USE_WIN32_API
|
@@ -0,0 +1,368 @@
|
|
1
|
+
// File: lzham_task_pool_win32.h
|
2
|
+
// See Copyright Notice and license at the end of include/lzham.h
|
3
|
+
#pragma once
|
4
|
+
|
5
|
+
#if LZHAM_USE_WIN32_API
|
6
|
+
|
7
|
+
#if LZHAM_NO_ATOMICS
|
8
|
+
#error No atomic operations defined in lzham_platform.h!
|
9
|
+
#endif
|
10
|
+
|
11
|
+
namespace lzham
|
12
|
+
{
|
13
|
+
class semaphore
|
14
|
+
{
|
15
|
+
LZHAM_NO_COPY_OR_ASSIGNMENT_OP(semaphore);
|
16
|
+
|
17
|
+
public:
|
18
|
+
semaphore(long initialCount = 0, long maximumCount = 1, const char* pName = NULL)
|
19
|
+
{
|
20
|
+
m_handle = CreateSemaphoreA(NULL, initialCount, maximumCount, pName);
|
21
|
+
if (NULL == m_handle)
|
22
|
+
{
|
23
|
+
LZHAM_FAIL("semaphore: CreateSemaphore() failed");
|
24
|
+
}
|
25
|
+
}
|
26
|
+
|
27
|
+
~semaphore()
|
28
|
+
{
|
29
|
+
if (m_handle)
|
30
|
+
{
|
31
|
+
CloseHandle(m_handle);
|
32
|
+
m_handle = NULL;
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
inline HANDLE get_handle(void) const { return m_handle; }
|
37
|
+
|
38
|
+
void release(long releaseCount = 1)
|
39
|
+
{
|
40
|
+
if (0 == ReleaseSemaphore(m_handle, releaseCount, NULL))
|
41
|
+
{
|
42
|
+
LZHAM_FAIL("semaphore: ReleaseSemaphore() failed");
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
bool wait(uint32 milliseconds = UINT32_MAX)
|
47
|
+
{
|
48
|
+
LZHAM_ASSUME(INFINITE == UINT32_MAX);
|
49
|
+
|
50
|
+
DWORD result = WaitForSingleObject(m_handle, milliseconds);
|
51
|
+
|
52
|
+
if (WAIT_FAILED == result)
|
53
|
+
{
|
54
|
+
LZHAM_FAIL("semaphore: WaitForSingleObject() failed");
|
55
|
+
}
|
56
|
+
|
57
|
+
return WAIT_OBJECT_0 == result;
|
58
|
+
}
|
59
|
+
|
60
|
+
private:
|
61
|
+
HANDLE m_handle;
|
62
|
+
};
|
63
|
+
|
64
|
+
template<typename T>
|
65
|
+
class tsstack
|
66
|
+
{
|
67
|
+
public:
|
68
|
+
inline tsstack(bool use_freelist = true) :
|
69
|
+
m_use_freelist(use_freelist)
|
70
|
+
{
|
71
|
+
LZHAM_VERIFY(((ptr_bits_t)this & (LZHAM_GET_ALIGNMENT(tsstack) - 1)) == 0);
|
72
|
+
InitializeSListHead(&m_stack_head);
|
73
|
+
InitializeSListHead(&m_freelist_head);
|
74
|
+
}
|
75
|
+
|
76
|
+
inline ~tsstack()
|
77
|
+
{
|
78
|
+
clear();
|
79
|
+
}
|
80
|
+
|
81
|
+
inline void clear()
|
82
|
+
{
|
83
|
+
for ( ; ; )
|
84
|
+
{
|
85
|
+
node* pNode = (node*)InterlockedPopEntrySList(&m_stack_head);
|
86
|
+
if (!pNode)
|
87
|
+
break;
|
88
|
+
|
89
|
+
LZHAM_MEMORY_IMPORT_BARRIER
|
90
|
+
|
91
|
+
helpers::destruct(&pNode->m_obj);
|
92
|
+
|
93
|
+
lzham_free(pNode);
|
94
|
+
}
|
95
|
+
|
96
|
+
flush_freelist();
|
97
|
+
}
|
98
|
+
|
99
|
+
inline void flush_freelist()
|
100
|
+
{
|
101
|
+
if (!m_use_freelist)
|
102
|
+
return;
|
103
|
+
|
104
|
+
for ( ; ; )
|
105
|
+
{
|
106
|
+
node* pNode = (node*)InterlockedPopEntrySList(&m_freelist_head);
|
107
|
+
if (!pNode)
|
108
|
+
break;
|
109
|
+
|
110
|
+
LZHAM_MEMORY_IMPORT_BARRIER
|
111
|
+
|
112
|
+
lzham_free(pNode);
|
113
|
+
}
|
114
|
+
}
|
115
|
+
|
116
|
+
inline bool try_push(const T& obj)
|
117
|
+
{
|
118
|
+
node* pNode = alloc_node();
|
119
|
+
if (!pNode)
|
120
|
+
return false;
|
121
|
+
|
122
|
+
helpers::construct(&pNode->m_obj, obj);
|
123
|
+
|
124
|
+
LZHAM_MEMORY_EXPORT_BARRIER
|
125
|
+
|
126
|
+
InterlockedPushEntrySList(&m_stack_head, &pNode->m_slist_entry);
|
127
|
+
|
128
|
+
return true;
|
129
|
+
}
|
130
|
+
|
131
|
+
inline bool pop(T& obj)
|
132
|
+
{
|
133
|
+
node* pNode = (node*)InterlockedPopEntrySList(&m_stack_head);
|
134
|
+
if (!pNode)
|
135
|
+
return false;
|
136
|
+
|
137
|
+
LZHAM_MEMORY_IMPORT_BARRIER
|
138
|
+
|
139
|
+
obj = pNode->m_obj;
|
140
|
+
|
141
|
+
helpers::destruct(&pNode->m_obj);
|
142
|
+
|
143
|
+
free_node(pNode);
|
144
|
+
|
145
|
+
return true;
|
146
|
+
}
|
147
|
+
|
148
|
+
private:
|
149
|
+
SLIST_HEADER m_stack_head;
|
150
|
+
SLIST_HEADER m_freelist_head;
|
151
|
+
|
152
|
+
struct node
|
153
|
+
{
|
154
|
+
SLIST_ENTRY m_slist_entry;
|
155
|
+
T m_obj;
|
156
|
+
};
|
157
|
+
|
158
|
+
bool m_use_freelist;
|
159
|
+
|
160
|
+
inline node* alloc_node()
|
161
|
+
{
|
162
|
+
node* pNode = m_use_freelist ? (node*)InterlockedPopEntrySList(&m_freelist_head) : NULL;
|
163
|
+
|
164
|
+
if (!pNode)
|
165
|
+
pNode = (node*)lzham_malloc(sizeof(node));
|
166
|
+
|
167
|
+
return pNode;
|
168
|
+
}
|
169
|
+
|
170
|
+
inline void free_node(node* pNode)
|
171
|
+
{
|
172
|
+
if (m_use_freelist)
|
173
|
+
InterlockedPushEntrySList(&m_freelist_head, &pNode->m_slist_entry);
|
174
|
+
else
|
175
|
+
lzham_free(pNode);
|
176
|
+
}
|
177
|
+
};
|
178
|
+
|
179
|
+
class task_pool
|
180
|
+
{
|
181
|
+
public:
|
182
|
+
task_pool();
|
183
|
+
task_pool(uint num_threads);
|
184
|
+
~task_pool();
|
185
|
+
|
186
|
+
enum { cMaxThreads = LZHAM_MAX_HELPER_THREADS };
|
187
|
+
bool init(uint num_threads);
|
188
|
+
void deinit();
|
189
|
+
|
190
|
+
inline uint get_num_threads() const { return m_num_threads; }
|
191
|
+
inline uint get_num_outstanding_tasks() const { return m_num_outstanding_tasks; }
|
192
|
+
|
193
|
+
// C-style task callback
|
194
|
+
typedef void (*task_callback_func)(uint64 data, void* pData_ptr);
|
195
|
+
bool queue_task(task_callback_func pFunc, uint64 data = 0, void* pData_ptr = NULL);
|
196
|
+
|
197
|
+
class executable_task
|
198
|
+
{
|
199
|
+
public:
|
200
|
+
virtual void execute_task(uint64 data, void* pData_ptr) = 0;
|
201
|
+
};
|
202
|
+
|
203
|
+
// It's the caller's responsibility to delete pObj within the execute_task() method, if needed!
|
204
|
+
bool queue_task(executable_task* pObj, uint64 data = 0, void* pData_ptr = NULL);
|
205
|
+
|
206
|
+
template<typename S, typename T>
|
207
|
+
inline bool queue_object_task(S* pObject, T pObject_method, uint64 data = 0, void* pData_ptr = NULL);
|
208
|
+
|
209
|
+
template<typename S, typename T>
|
210
|
+
inline bool queue_multiple_object_tasks(S* pObject, T pObject_method, uint64 first_data, uint num_tasks, void* pData_ptr = NULL);
|
211
|
+
|
212
|
+
void join();
|
213
|
+
|
214
|
+
private:
|
215
|
+
struct task
|
216
|
+
{
|
217
|
+
//inline task() : m_data(0), m_pData_ptr(NULL), m_pObj(NULL), m_flags(0) { }
|
218
|
+
|
219
|
+
uint64 m_data;
|
220
|
+
void* m_pData_ptr;
|
221
|
+
|
222
|
+
union
|
223
|
+
{
|
224
|
+
task_callback_func m_callback;
|
225
|
+
executable_task* m_pObj;
|
226
|
+
};
|
227
|
+
|
228
|
+
uint m_flags;
|
229
|
+
};
|
230
|
+
|
231
|
+
tsstack<task> m_task_stack;
|
232
|
+
|
233
|
+
uint m_num_threads;
|
234
|
+
HANDLE m_threads[cMaxThreads];
|
235
|
+
|
236
|
+
semaphore m_tasks_available;
|
237
|
+
|
238
|
+
enum task_flags
|
239
|
+
{
|
240
|
+
cTaskFlagObject = 1
|
241
|
+
};
|
242
|
+
|
243
|
+
volatile atomic32_t m_num_outstanding_tasks;
|
244
|
+
volatile atomic32_t m_exit_flag;
|
245
|
+
|
246
|
+
void process_task(task& tsk);
|
247
|
+
|
248
|
+
static unsigned __stdcall thread_func(void* pContext);
|
249
|
+
};
|
250
|
+
|
251
|
+
enum object_task_flags
|
252
|
+
{
|
253
|
+
cObjectTaskFlagDefault = 0,
|
254
|
+
cObjectTaskFlagDeleteAfterExecution = 1
|
255
|
+
};
|
256
|
+
|
257
|
+
template<typename T>
|
258
|
+
class object_task : public task_pool::executable_task
|
259
|
+
{
|
260
|
+
public:
|
261
|
+
object_task(uint flags = cObjectTaskFlagDefault) :
|
262
|
+
m_pObject(NULL),
|
263
|
+
m_pMethod(NULL),
|
264
|
+
m_flags(flags)
|
265
|
+
{
|
266
|
+
}
|
267
|
+
|
268
|
+
typedef void (T::*object_method_ptr)(uint64 data, void* pData_ptr);
|
269
|
+
|
270
|
+
object_task(T* pObject, object_method_ptr pMethod, uint flags = cObjectTaskFlagDefault) :
|
271
|
+
m_pObject(pObject),
|
272
|
+
m_pMethod(pMethod),
|
273
|
+
m_flags(flags)
|
274
|
+
{
|
275
|
+
LZHAM_ASSERT(pObject && pMethod);
|
276
|
+
}
|
277
|
+
|
278
|
+
void init(T* pObject, object_method_ptr pMethod, uint flags = cObjectTaskFlagDefault)
|
279
|
+
{
|
280
|
+
LZHAM_ASSERT(pObject && pMethod);
|
281
|
+
|
282
|
+
m_pObject = pObject;
|
283
|
+
m_pMethod = pMethod;
|
284
|
+
m_flags = flags;
|
285
|
+
}
|
286
|
+
|
287
|
+
T* get_object() const { return m_pObject; }
|
288
|
+
object_method_ptr get_method() const { return m_pMethod; }
|
289
|
+
|
290
|
+
virtual void execute_task(uint64 data, void* pData_ptr)
|
291
|
+
{
|
292
|
+
(m_pObject->*m_pMethod)(data, pData_ptr);
|
293
|
+
|
294
|
+
if (m_flags & cObjectTaskFlagDeleteAfterExecution)
|
295
|
+
lzham_delete(this);
|
296
|
+
}
|
297
|
+
|
298
|
+
protected:
|
299
|
+
T* m_pObject;
|
300
|
+
|
301
|
+
object_method_ptr m_pMethod;
|
302
|
+
|
303
|
+
uint m_flags;
|
304
|
+
};
|
305
|
+
|
306
|
+
template<typename S, typename T>
|
307
|
+
inline bool task_pool::queue_object_task(S* pObject, T pObject_method, uint64 data, void* pData_ptr)
|
308
|
+
{
|
309
|
+
object_task<S> *pTask = lzham_new< object_task<S> >(pObject, pObject_method, cObjectTaskFlagDeleteAfterExecution);
|
310
|
+
if (!pTask)
|
311
|
+
return false;
|
312
|
+
return queue_task(pTask, data, pData_ptr);
|
313
|
+
}
|
314
|
+
|
315
|
+
template<typename S, typename T>
|
316
|
+
inline bool task_pool::queue_multiple_object_tasks(S* pObject, T pObject_method, uint64 first_data, uint num_tasks, void* pData_ptr)
|
317
|
+
{
|
318
|
+
LZHAM_ASSERT(m_num_threads);
|
319
|
+
LZHAM_ASSERT(pObject);
|
320
|
+
LZHAM_ASSERT(num_tasks);
|
321
|
+
if (!num_tasks)
|
322
|
+
return true;
|
323
|
+
|
324
|
+
bool status = true;
|
325
|
+
|
326
|
+
uint i;
|
327
|
+
for (i = 0; i < num_tasks; i++)
|
328
|
+
{
|
329
|
+
task tsk;
|
330
|
+
|
331
|
+
tsk.m_pObj = lzham_new< object_task<S> >(pObject, pObject_method, cObjectTaskFlagDeleteAfterExecution);
|
332
|
+
if (!tsk.m_pObj)
|
333
|
+
{
|
334
|
+
status = false;
|
335
|
+
break;
|
336
|
+
}
|
337
|
+
|
338
|
+
tsk.m_data = first_data + i;
|
339
|
+
tsk.m_pData_ptr = pData_ptr;
|
340
|
+
tsk.m_flags = cTaskFlagObject;
|
341
|
+
|
342
|
+
if (!m_task_stack.try_push(tsk))
|
343
|
+
{
|
344
|
+
status = false;
|
345
|
+
break;
|
346
|
+
}
|
347
|
+
}
|
348
|
+
|
349
|
+
if (i)
|
350
|
+
{
|
351
|
+
atomic_add32(&m_num_outstanding_tasks, i);
|
352
|
+
|
353
|
+
m_tasks_available.release(i);
|
354
|
+
}
|
355
|
+
|
356
|
+
return status;
|
357
|
+
}
|
358
|
+
|
359
|
+
inline void lzham_sleep(unsigned int milliseconds)
|
360
|
+
{
|
361
|
+
Sleep(milliseconds);
|
362
|
+
}
|
363
|
+
|
364
|
+
uint lzham_get_max_helper_threads();
|
365
|
+
|
366
|
+
} // namespace lzham
|
367
|
+
|
368
|
+
#endif // LZHAM_USE_WIN32_API
|