Merge commit '6f07e4eedc6b624b1f9ae1004ad3e6a77027e028' into second-tp-attempt
Conflicts: src/backend/threads.c
This commit is contained in:
commit
fc15a2ac2c
8 changed files with 60 additions and 69 deletions
|
|
@ -32,7 +32,7 @@ iconcommand = python $(top_srcdir)/admin/render_icon.py
|
||||||
32x32pre = $(prerendereddir)/32x32
|
32x32pre = $(prerendereddir)/32x32
|
||||||
48x48pre = $(prerendereddir)/48x48
|
48x48pre = $(prerendereddir)/48x48
|
||||||
|
|
||||||
dist_pkgdata_DATA += \
|
icons = \
|
||||||
$(16x16)/app-icon.png $(22x22)/app-icon.png $(24x24)/app-icon.png $(32x32)/app-icon.png $(48x48)/app-icon.png \
|
$(16x16)/app-icon.png $(22x22)/app-icon.png $(24x24)/app-icon.png $(32x32)/app-icon.png $(48x48)/app-icon.png \
|
||||||
$(16x16)/tool-arrow.png $(22x22)/tool-arrow.png $(24x24)/tool-arrow.png $(32x32)/tool-arrow.png $(48x48)/tool-arrow.png \
|
$(16x16)/tool-arrow.png $(22x22)/tool-arrow.png $(24x24)/tool-arrow.png $(32x32)/tool-arrow.png $(48x48)/tool-arrow.png \
|
||||||
$(16x16)/tool-i-beam.png $(22x22)/tool-i-beam.png $(24x24)/tool-i-beam.png $(32x32)/tool-i-beam.png $(48x48)/tool-i-beam.png \
|
$(16x16)/tool-i-beam.png $(22x22)/tool-i-beam.png $(24x24)/tool-i-beam.png $(32x32)/tool-i-beam.png $(48x48)/tool-i-beam.png \
|
||||||
|
|
@ -44,6 +44,10 @@ dist_pkgdata_DATA += \
|
||||||
$(16x16)/panel-timeline.png \
|
$(16x16)/panel-timeline.png \
|
||||||
$(16x16)/panel-viewer.png $(22x22)/panel-viewer.png $(32x32)/panel-viewer.png
|
$(16x16)/panel-viewer.png $(22x22)/panel-viewer.png $(32x32)/panel-viewer.png
|
||||||
|
|
||||||
|
dist_pkgdata_DATA += $(icons)
|
||||||
|
|
||||||
|
all: $(icons)
|
||||||
|
|
||||||
clean-local:
|
clean-local:
|
||||||
rm -rf $(16x16) $(22x22) $(24x24) $(32x32) $(48x48)
|
rm -rf $(16x16) $(22x22) $(24x24) $(32x32) $(48x48)
|
||||||
|
|
||||||
|
|
@ -75,19 +79,19 @@ $(16x16)/track-unlocked.png : $(svgdir)/track-unlocked.svg $(top_builddir)/rsvg-
|
||||||
|
|
||||||
# Panels
|
# Panels
|
||||||
|
|
||||||
$(16x16)/panel-resources.png:
|
$(16x16)/panel-resources.png: $(16x16pre)/panel-resources.png
|
||||||
cp $(16x16pre)/panel-resources.png $(16x16)
|
cp $(16x16pre)/panel-resources.png $(16x16)
|
||||||
$(22x22)/panel-resources.png:
|
$(22x22)/panel-resources.png: $(22x22pre)/panel-resources.png
|
||||||
cp $(22x22pre)/panel-resources.png $(22x22)
|
cp $(22x22pre)/panel-resources.png $(22x22)
|
||||||
$(32x32)/panel-resources.png:
|
$(32x32)/panel-resources.png: $(32x32pre)/panel-resources.png
|
||||||
cp $(32x32pre)/panel-resources.png $(32x32)
|
cp $(32x32pre)/panel-resources.png $(32x32)
|
||||||
|
|
||||||
$(16x16)/panel-timeline.png:
|
$(16x16)/panel-timeline.png: $(16x16pre)/panel-timeline.png
|
||||||
cp $(16x16pre)/panel-timeline.png $(16x16)
|
cp $(16x16pre)/panel-timeline.png $(16x16)
|
||||||
|
|
||||||
$(16x16)/panel-viewer.png:
|
$(16x16)/panel-viewer.png: $(16x16pre)/panel-viewer.png
|
||||||
cp $(16x16pre)/panel-viewer.png $(16x16)
|
cp $(16x16pre)/panel-viewer.png $(16x16)
|
||||||
$(22x22)/panel-viewer.png:
|
$(22x22)/panel-viewer.png: $(22x22pre)/panel-viewer.png
|
||||||
cp $(22x22pre)/panel-viewer.png $(22x22)
|
cp $(22x22pre)/panel-viewer.png $(22x22)
|
||||||
$(32x32)/panel-viewer.png:
|
$(32x32)/panel-viewer.png: $(32x32pre)/panel-viewer.png
|
||||||
cp $(32x32pre)/panel-viewer.png $(32x32)
|
cp $(32x32pre)/panel-viewer.png $(32x32)
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
#include "backend/filehandlecache.h"
|
#include "backend/filehandlecache.h"
|
||||||
#include "backend/filedescriptor.h"
|
#include "backend/filedescriptor.h"
|
||||||
#include "backend/mmapcache.h"
|
#include "backend/mmapcache.h"
|
||||||
|
#include "backend/threadpool.h"
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
|
|
@ -63,6 +64,9 @@ lumiera_backend_init (void)
|
||||||
//NOBUG_INIT_FLAG (mmapcache);
|
//NOBUG_INIT_FLAG (mmapcache);
|
||||||
|
|
||||||
TRACE (backend_dbg);
|
TRACE (backend_dbg);
|
||||||
|
|
||||||
|
lumiera_threadpool_init ();
|
||||||
|
|
||||||
lumiera_filedescriptor_registry_init ();
|
lumiera_filedescriptor_registry_init ();
|
||||||
|
|
||||||
lumiera_backend_pagesize = sysconf(_SC_PAGESIZE);
|
lumiera_backend_pagesize = sysconf(_SC_PAGESIZE);
|
||||||
|
|
@ -112,4 +116,5 @@ lumiera_backend_destroy (void)
|
||||||
lumiera_mmapcache_delete ();
|
lumiera_mmapcache_delete ();
|
||||||
lumiera_filehandlecache_delete ();
|
lumiera_filehandlecache_delete ();
|
||||||
lumiera_filedescriptor_registry_destroy ();
|
lumiera_filedescriptor_registry_destroy ();
|
||||||
|
lumiera_threadpool_destroy ();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,8 +55,6 @@ lumiera_threadpool_init(void)
|
||||||
{
|
{
|
||||||
llist_init (&threadpool.pool[i].working_list);
|
llist_init (&threadpool.pool[i].working_list);
|
||||||
llist_init (&threadpool.pool[i].idle_list);
|
llist_init (&threadpool.pool[i].idle_list);
|
||||||
threadpool.pool[i].thread_count = 0;
|
|
||||||
threadpool.pool[i].idle_thread_count = 0;
|
|
||||||
threadpool.pool[i].status = LUMIERA_THREADPOOL_ONLINE;
|
threadpool.pool[i].status = LUMIERA_THREADPOOL_ONLINE;
|
||||||
|
|
||||||
//TODO: configure each pools' pthread_attrs appropriately
|
//TODO: configure each pools' pthread_attrs appropriately
|
||||||
|
|
@ -95,24 +93,12 @@ lumiera_threadpool_destroy(void)
|
||||||
|
|
||||||
LUMIERA_CONDITION_SECTION (threadpool, &threadpool.pool[i].sync)
|
LUMIERA_CONDITION_SECTION (threadpool, &threadpool.pool[i].sync)
|
||||||
{
|
{
|
||||||
REQUIRE (threadpool.pool[i].thread_count
|
ENSURE (llist_is_empty (&threadpool.pool[i].working_list),
|
||||||
== threadpool.pool[i].idle_thread_count
|
"threads are still running");
|
||||||
&& 0 == llist_count (&threadpool.pool[i].working_list),
|
|
||||||
"%d(llist_count=%d) threads are still running",
|
|
||||||
threadpool.pool[i].thread_count
|
|
||||||
- threadpool.pool[i].idle_thread_count,
|
|
||||||
llist_count (&threadpool.pool[i].working_list));
|
|
||||||
REQUIRE ((int)(llist_count (&threadpool.pool[i].working_list)
|
|
||||||
+ llist_count (&threadpool.pool[i].idle_list))
|
|
||||||
== threadpool.pool[i].thread_count,
|
|
||||||
"threadpool counter miscalculation (working_list count = %u, idle_list count = %u, thread_count = %d )",
|
|
||||||
llist_count (&threadpool.pool[i].working_list),
|
|
||||||
llist_count (&threadpool.pool[i].idle_list),
|
|
||||||
threadpool.pool[i].thread_count);
|
|
||||||
LLIST_WHILE_HEAD (&threadpool.pool[i].idle_list, t)
|
LLIST_WHILE_HEAD (&threadpool.pool[i].idle_list, t)
|
||||||
{
|
{
|
||||||
lumiera_thread_delete ((LumieraThread)t);
|
lumiera_thread_delete ((LumieraThread)t);
|
||||||
threadpool.pool[i].thread_count--;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lumiera_condition_destroy (&threadpool.pool[i].sync, &NOBUG_FLAG (threadpool));
|
lumiera_condition_destroy (&threadpool.pool[i].sync, &NOBUG_FLAG (threadpool));
|
||||||
|
|
@ -146,28 +132,16 @@ lumiera_threadpool_acquire_thread (enum lumiera_thread_class kind,
|
||||||
&threadpool.pool[kind].pthread_attrs);
|
&threadpool.pool[kind].pthread_attrs);
|
||||||
ENSURE (ret, "did not create a valid thread");
|
ENSURE (ret, "did not create a valid thread");
|
||||||
TODO ("no error handing, let the resourcecollector do it, no need when returning the thread");
|
TODO ("no error handing, let the resourcecollector do it, no need when returning the thread");
|
||||||
threadpool.pool[kind].thread_count++;
|
|
||||||
LUMIERA_CONDITION_WAIT (!llist_is_empty (&threadpool.pool[kind].idle_list));
|
LUMIERA_CONDITION_WAIT (!llist_is_empty (&threadpool.pool[kind].idle_list));
|
||||||
}
|
}
|
||||||
// use an existing thread, pick the first one
|
// use an existing thread, pick the first one
|
||||||
// remove it from the pool's list
|
// remove it from the pool's list
|
||||||
ret = (LumieraThread) (llist_head (&threadpool.pool[kind].idle_list));
|
ret = (LumieraThread) (llist_head (&threadpool.pool[kind].idle_list));
|
||||||
|
|
||||||
ENSURE (ret, "did not find a valid thread");
|
|
||||||
|
|
||||||
REQUIRE (ret->state == LUMIERA_THREADSTATE_IDLE, "trying to return a non-idle thread (state=%s)", lumiera_threadstate_names[ret->state]);
|
REQUIRE (ret->state == LUMIERA_THREADSTATE_IDLE, "trying to return a non-idle thread (state=%s)", lumiera_threadstate_names[ret->state]);
|
||||||
|
|
||||||
// move thread to the working_list
|
// move thread to the working_list
|
||||||
llist_insert_head (&threadpool.pool[kind].working_list, &ret->node);
|
llist_insert_head (&threadpool.pool[kind].working_list, &ret->node);
|
||||||
|
|
||||||
threadpool.pool[kind].idle_thread_count--; // cheaper than using llist_count
|
|
||||||
REQUIRE ((int)(llist_count (&threadpool.pool[kind].working_list)
|
|
||||||
+ llist_count (&threadpool.pool[kind].idle_list))
|
|
||||||
== threadpool.pool[kind].thread_count,
|
|
||||||
"threadpool counter miscalculation (working_list count = %u, idle_list count = %u, thread_count = %d )",
|
|
||||||
llist_count (&threadpool.pool[kind].working_list),
|
|
||||||
llist_count (&threadpool.pool[kind].idle_list),
|
|
||||||
threadpool.pool[kind].thread_count);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
|
@ -178,6 +152,7 @@ lumiera_threadpool_release_thread(LumieraThread thread)
|
||||||
{
|
{
|
||||||
TRACE (threadpool);
|
TRACE (threadpool);
|
||||||
REQUIRE (thread, "invalid thread given");
|
REQUIRE (thread, "invalid thread given");
|
||||||
|
thread->kind = thread->kind&0xff;
|
||||||
REQUIRE (thread->kind < LUMIERA_THREADCLASS_COUNT, "thread belongs to an unknown pool kind: %d", thread->kind);
|
REQUIRE (thread->kind < LUMIERA_THREADCLASS_COUNT, "thread belongs to an unknown pool kind: %d", thread->kind);
|
||||||
|
|
||||||
REQUIRE (thread->state != LUMIERA_THREADSTATE_IDLE, "trying to park an already idle thread");
|
REQUIRE (thread->state != LUMIERA_THREADSTATE_IDLE, "trying to park an already idle thread");
|
||||||
|
|
@ -192,16 +167,6 @@ lumiera_threadpool_release_thread(LumieraThread thread)
|
||||||
// move thread to the idle_list
|
// move thread to the idle_list
|
||||||
llist_insert_head (&threadpool.pool[thread->kind].idle_list, &thread->node);
|
llist_insert_head (&threadpool.pool[thread->kind].idle_list, &thread->node);
|
||||||
|
|
||||||
threadpool.pool[thread->kind].idle_thread_count++; // cheaper than using llist_count
|
|
||||||
REQUIRE ((int)(llist_count (&threadpool.pool[thread->kind].working_list)
|
|
||||||
+ llist_count (&threadpool.pool[thread->kind].idle_list))
|
|
||||||
== threadpool.pool[thread->kind].thread_count,
|
|
||||||
"threadpool counter miscalculation (working_list count = %u, idle_list count = %u, thread_count = %d )",
|
|
||||||
llist_count (&threadpool.pool[thread->kind].working_list),
|
|
||||||
llist_count (&threadpool.pool[thread->kind].idle_list),
|
|
||||||
threadpool.pool[thread->kind].thread_count);
|
|
||||||
|
|
||||||
REQUIRE (!llist_is_empty (&threadpool.pool[thread->kind].idle_list), "thread pool is still empty after insertion");
|
|
||||||
LUMIERA_CONDITION_BROADCAST;
|
LUMIERA_CONDITION_BROADCAST;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -75,8 +75,6 @@ struct lumiera_threadpool_struct
|
||||||
{
|
{
|
||||||
llist working_list;
|
llist working_list;
|
||||||
llist idle_list;
|
llist idle_list;
|
||||||
int thread_count;
|
|
||||||
int idle_thread_count;
|
|
||||||
pthread_attr_t pthread_attrs;
|
pthread_attr_t pthread_attrs;
|
||||||
lumiera_condition sync;
|
lumiera_condition sync;
|
||||||
enum lumiera_threadpool_state status;
|
enum lumiera_threadpool_state status;
|
||||||
|
|
|
||||||
|
|
@ -92,25 +92,30 @@ thread_loop (void* thread)
|
||||||
t->rh = &lumiera_lock_section_.rh;
|
t->rh = &lumiera_lock_section_.rh;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
lumiera_threadpool_release_thread(t);
|
||||||
|
LUMIERA_CONDITION_WAIT (t->state != LUMIERA_THREADSTATE_IDLE);
|
||||||
|
INFO (threads, "Thread awaken with state %d", t->state);
|
||||||
|
|
||||||
// NULL function means: no work to do
|
// NULL function means: no work to do
|
||||||
INFO (threads, "function %p", t->function);
|
INFO (threads, "function %p", t->function);
|
||||||
if (t->function)
|
if (t->function)
|
||||||
t->function (t->arguments);
|
t->function (t->arguments);
|
||||||
lumiera_threadpool_release_thread(t);
|
TRACE (threads, "function done");
|
||||||
LUMIERA_CONDITION_WAIT (t->state != LUMIERA_THREADSTATE_IDLE);
|
|
||||||
INFO (threads, "Thread awaken with state %d", t->state);
|
if (t->kind & LUMIERA_THREAD_JOINABLE)
|
||||||
|
{
|
||||||
|
INFO (threads, "Thread zombified");
|
||||||
|
/* move error state to data the other thread will it pick up from there */
|
||||||
|
t->arguments = (void*)lumiera_error ();
|
||||||
|
t->state = LUMIERA_THREADSTATE_ZOMBIE;
|
||||||
|
LUMIERA_CONDITION_SIGNAL;
|
||||||
|
LUMIERA_CONDITION_WAIT (t->state == LUMIERA_THREADSTATE_JOINED);
|
||||||
|
INFO (threads, "Thread joined");
|
||||||
|
}
|
||||||
|
|
||||||
} while (t->state != LUMIERA_THREADSTATE_SHUTDOWN);
|
} while (t->state != LUMIERA_THREADSTATE_SHUTDOWN);
|
||||||
// SHUTDOWN state
|
// SHUTDOWN state
|
||||||
|
|
||||||
if (t->kind & LUMIERA_THREAD_JOINABLE)
|
|
||||||
{
|
|
||||||
INFO (threads, "Thread zombified");
|
|
||||||
/* move error state to data the other thread will it pick up from there */
|
|
||||||
t->arguments = (void*)lumiera_error ();
|
|
||||||
t->state = LUMIERA_THREADSTATE_ZOMBIE;
|
|
||||||
LUMIERA_CONDITION_WAIT (t->state == LUMIERA_THREADSTATE_JOINED);
|
|
||||||
INFO (threads, "Thread joined");
|
|
||||||
}
|
|
||||||
|
|
||||||
INFO (threads, "Thread Shutdown");
|
INFO (threads, "Thread Shutdown");
|
||||||
}
|
}
|
||||||
|
|
@ -121,7 +126,7 @@ thread_loop (void* thread)
|
||||||
// when this is called it should have already been decided that the function
|
// when this is called it should have already been decided that the function
|
||||||
// shall run in parallel, as a thread
|
// shall run in parallel, as a thread
|
||||||
LumieraThread
|
LumieraThread
|
||||||
lumiera_thread_run (enum lumiera_thread_class kind,
|
lumiera_thread_run (int kind,
|
||||||
void (*function)(void *),
|
void (*function)(void *),
|
||||||
void * arg,
|
void * arg,
|
||||||
const char* purpose,
|
const char* purpose,
|
||||||
|
|
@ -131,12 +136,12 @@ lumiera_thread_run (enum lumiera_thread_class kind,
|
||||||
// REQUIRE (function, "invalid function");
|
// REQUIRE (function, "invalid function");
|
||||||
|
|
||||||
// ask the threadpool for a thread (it might create a new one)
|
// ask the threadpool for a thread (it might create a new one)
|
||||||
LumieraThread self = lumiera_threadpool_acquire_thread (kind, purpose, flag);
|
LumieraThread self = lumiera_threadpool_acquire_thread (kind&0xff, purpose, flag);
|
||||||
|
|
||||||
// set the function and data to be run
|
// set the function and data to be run
|
||||||
self->function = function;
|
self->function = function;
|
||||||
self->arguments = arg;
|
self->arguments = arg;
|
||||||
|
self->kind = kind;
|
||||||
self->deadline.tv_sec = 0;
|
self->deadline.tv_sec = 0;
|
||||||
|
|
||||||
// and let it really run (signal the condition var, the thread waits on it)
|
// and let it really run (signal the condition var, the thread waits on it)
|
||||||
|
|
@ -294,7 +299,7 @@ lumiera_thread_sync_other (LumieraThread other)
|
||||||
|
|
||||||
LUMIERA_CONDITION_SECTION (threads, &other->signal)
|
LUMIERA_CONDITION_SECTION (threads, &other->signal)
|
||||||
{
|
{
|
||||||
REQUIRE (other->state == LUMIERA_THREADSTATE_SYNCING, "the other thread is in the wrong state: %s", lumiera_threadstate_names[other->state]); TODO("Runtime error when state expectation isn't met");
|
LUMIERA_CONDITION_WAIT (other->state == LUMIERA_THREADSTATE_SYNCING);
|
||||||
other->state = LUMIERA_THREADSTATE_RUNNING;
|
other->state = LUMIERA_THREADSTATE_RUNNING;
|
||||||
LUMIERA_CONDITION_SIGNAL;
|
LUMIERA_CONDITION_SIGNAL;
|
||||||
}
|
}
|
||||||
|
|
@ -311,6 +316,7 @@ lumiera_thread_sync (void)
|
||||||
REQUIRE(self, "not a lumiera thread");
|
REQUIRE(self, "not a lumiera thread");
|
||||||
|
|
||||||
self->state = LUMIERA_THREADSTATE_SYNCING;
|
self->state = LUMIERA_THREADSTATE_SYNCING;
|
||||||
|
lumiera_condition_signal (&self->signal, &NOBUG_FLAG(threads));
|
||||||
|
|
||||||
TODO("error handing, maybe timed mutex (using the threads heartbeat timeout, shortly before timeout)");
|
TODO("error handing, maybe timed mutex (using the threads heartbeat timeout, shortly before timeout)");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ enum lumiera_thread_class
|
||||||
LUMIERA_THREAD_CLASSES
|
LUMIERA_THREAD_CLASSES
|
||||||
/** this just denotes the number of classes listed above,
|
/** this just denotes the number of classes listed above,
|
||||||
it is used to create arrays **/
|
it is used to create arrays **/
|
||||||
LUMIERA_THREADCLASS_COUNT,
|
LUMIERA_THREADCLASS_COUNT, /* must be <= 256, thats easy or? */
|
||||||
|
|
||||||
// .. various thread flags follow
|
// .. various thread flags follow
|
||||||
/**
|
/**
|
||||||
|
|
@ -83,12 +83,12 @@ enum lumiera_thread_class
|
||||||
* The Thread must be very careful with locking, better don't.
|
* The Thread must be very careful with locking, better don't.
|
||||||
* TODO explain syncronization issues
|
* TODO explain syncronization issues
|
||||||
**/
|
**/
|
||||||
LUMIERA_THREAD_OR_NOT = 1<<16,
|
LUMIERA_THREAD_OR_NOT = 1<<8,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Thread must be joined finally
|
* Thread must be joined finally
|
||||||
**/
|
**/
|
||||||
LUMIERA_THREAD_JOINABLE = 1<<17
|
LUMIERA_THREAD_JOINABLE = 1<<9
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef LUMIERA_THREAD_CLASS
|
#undef LUMIERA_THREAD_CLASS
|
||||||
|
|
@ -195,7 +195,7 @@ lumiera_thread_delete (LumieraThread self);
|
||||||
* @param flag NoBug flag used for logging the thread startup and return
|
* @param flag NoBug flag used for logging the thread startup and return
|
||||||
*/
|
*/
|
||||||
LumieraThread
|
LumieraThread
|
||||||
lumiera_thread_run (enum lumiera_thread_class kind,
|
lumiera_thread_run (int kind,
|
||||||
void (*function)(void *),
|
void (*function)(void *),
|
||||||
void * arg,
|
void * arg,
|
||||||
const char* purpose,
|
const char* purpose,
|
||||||
|
|
|
||||||
|
|
@ -129,6 +129,13 @@ namespace backend {
|
||||||
// while the third thread wasn't created at all.
|
// while the third thread wasn't created at all.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
ThreadWrapperJoin_test()
|
||||||
|
{ lumiera_threadpool_init(); }
|
||||||
|
|
||||||
|
~ThreadWrapperJoin_test()
|
||||||
|
{ lumiera_threadpool_destroy(); }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,12 @@ namespace backend {
|
||||||
ASSERT (sum==checksum);
|
ASSERT (sum==checksum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
ThreadWrapper_test()
|
||||||
|
{ lumiera_threadpool_init(); }
|
||||||
|
|
||||||
|
~ThreadWrapper_test()
|
||||||
|
{ lumiera_threadpool_destroy(); }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue