diff --git a/icons/Makefile.am b/icons/Makefile.am index ce0990f26..8bffefd44 100644 --- a/icons/Makefile.am +++ b/icons/Makefile.am @@ -32,7 +32,7 @@ iconcommand = python $(top_srcdir)/admin/render_icon.py 32x32pre = $(prerendereddir)/32x32 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)/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 \ @@ -44,6 +44,10 @@ dist_pkgdata_DATA += \ $(16x16)/panel-timeline.png \ $(16x16)/panel-viewer.png $(22x22)/panel-viewer.png $(32x32)/panel-viewer.png +dist_pkgdata_DATA += $(icons) + +all: $(icons) + clean-local: rm -rf $(16x16) $(22x22) $(24x24) $(32x32) $(48x48) @@ -75,19 +79,19 @@ $(16x16)/track-unlocked.png : $(svgdir)/track-unlocked.svg $(top_builddir)/rsvg- # Panels -$(16x16)/panel-resources.png: +$(16x16)/panel-resources.png: $(16x16pre)/panel-resources.png cp $(16x16pre)/panel-resources.png $(16x16) -$(22x22)/panel-resources.png: +$(22x22)/panel-resources.png: $(22x22pre)/panel-resources.png cp $(22x22pre)/panel-resources.png $(22x22) -$(32x32)/panel-resources.png: +$(32x32)/panel-resources.png: $(32x32pre)/panel-resources.png cp $(32x32pre)/panel-resources.png $(32x32) -$(16x16)/panel-timeline.png: +$(16x16)/panel-timeline.png: $(16x16pre)/panel-timeline.png cp $(16x16pre)/panel-timeline.png $(16x16) -$(16x16)/panel-viewer.png: +$(16x16)/panel-viewer.png: $(16x16pre)/panel-viewer.png cp $(16x16pre)/panel-viewer.png $(16x16) -$(22x22)/panel-viewer.png: +$(22x22)/panel-viewer.png: $(22x22pre)/panel-viewer.png cp $(22x22pre)/panel-viewer.png $(22x22) -$(32x32)/panel-viewer.png: +$(32x32)/panel-viewer.png: $(32x32pre)/panel-viewer.png cp $(32x32pre)/panel-viewer.png $(32x32) diff --git a/src/backend/backend.c b/src/backend/backend.c index f0099f6f6..5440632a1 100644 --- a/src/backend/backend.c +++ b/src/backend/backend.c @@ -27,6 +27,7 @@ #include "backend/filehandlecache.h" #include "backend/filedescriptor.h" #include "backend/mmapcache.h" +#include "backend/threadpool.h" #include #include @@ -63,6 +64,9 @@ lumiera_backend_init (void) //NOBUG_INIT_FLAG (mmapcache); TRACE (backend_dbg); + + lumiera_threadpool_init (); + lumiera_filedescriptor_registry_init (); lumiera_backend_pagesize = sysconf(_SC_PAGESIZE); @@ -112,4 +116,5 @@ lumiera_backend_destroy (void) lumiera_mmapcache_delete (); lumiera_filehandlecache_delete (); lumiera_filedescriptor_registry_destroy (); + lumiera_threadpool_destroy (); } diff --git a/src/backend/threadpool.c b/src/backend/threadpool.c index b4811bc75..c26d27b5f 100644 --- a/src/backend/threadpool.c +++ b/src/backend/threadpool.c @@ -55,8 +55,6 @@ lumiera_threadpool_init(void) { llist_init (&threadpool.pool[i].working_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; //TODO: configure each pools' pthread_attrs appropriately @@ -95,24 +93,12 @@ lumiera_threadpool_destroy(void) LUMIERA_CONDITION_SECTION (threadpool, &threadpool.pool[i].sync) { - REQUIRE (threadpool.pool[i].thread_count - == threadpool.pool[i].idle_thread_count - && 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); + ENSURE (llist_is_empty (&threadpool.pool[i].working_list), + "threads are still running"); + LLIST_WHILE_HEAD (&threadpool.pool[i].idle_list, t) { lumiera_thread_delete ((LumieraThread)t); - threadpool.pool[i].thread_count--; } } 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); ENSURE (ret, "did not create a valid 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)); } // use an existing thread, pick the first one // remove it from the pool's 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]); // move thread to the working_list 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; @@ -178,6 +152,7 @@ lumiera_threadpool_release_thread(LumieraThread thread) { TRACE (threadpool); 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->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 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; } } diff --git a/src/backend/threadpool.h b/src/backend/threadpool.h index 5a3455d39..28bb21020 100644 --- a/src/backend/threadpool.h +++ b/src/backend/threadpool.h @@ -75,8 +75,6 @@ struct lumiera_threadpool_struct { llist working_list; llist idle_list; - int thread_count; - int idle_thread_count; pthread_attr_t pthread_attrs; lumiera_condition sync; enum lumiera_threadpool_state status; diff --git a/src/backend/threads.c b/src/backend/threads.c index f842f32ae..d4790ec91 100644 --- a/src/backend/threads.c +++ b/src/backend/threads.c @@ -92,25 +92,30 @@ thread_loop (void* thread) t->rh = &lumiera_lock_section_.rh; 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 INFO (threads, "function %p", t->function); if (t->function) t->function (t->arguments); - lumiera_threadpool_release_thread(t); - LUMIERA_CONDITION_WAIT (t->state != LUMIERA_THREADSTATE_IDLE); - INFO (threads, "Thread awaken with state %d", t->state); + TRACE (threads, "function done"); + + 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); // 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"); } @@ -121,7 +126,7 @@ thread_loop (void* thread) // when this is called it should have already been decided that the function // shall run in parallel, as a thread LumieraThread -lumiera_thread_run (enum lumiera_thread_class kind, +lumiera_thread_run (int kind, void (*function)(void *), void * arg, const char* purpose, @@ -131,12 +136,12 @@ lumiera_thread_run (enum lumiera_thread_class kind, // REQUIRE (function, "invalid function"); // 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 self->function = function; self->arguments = arg; - + self->kind = kind; self->deadline.tv_sec = 0; // 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) { - 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; LUMIERA_CONDITION_SIGNAL; } @@ -311,6 +316,7 @@ lumiera_thread_sync (void) REQUIRE(self, "not a lumiera thread"); 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)"); diff --git a/src/backend/threads.h b/src/backend/threads.h index 980a168e3..cc264d188 100644 --- a/src/backend/threads.h +++ b/src/backend/threads.h @@ -73,7 +73,7 @@ enum lumiera_thread_class LUMIERA_THREAD_CLASSES /** this just denotes the number of classes listed above, it is used to create arrays **/ - LUMIERA_THREADCLASS_COUNT, + LUMIERA_THREADCLASS_COUNT, /* must be <= 256, thats easy or? */ // .. various thread flags follow /** @@ -83,12 +83,12 @@ enum lumiera_thread_class * The Thread must be very careful with locking, better don't. * TODO explain syncronization issues **/ - LUMIERA_THREAD_OR_NOT = 1<<16, + LUMIERA_THREAD_OR_NOT = 1<<8, /** * Thread must be joined finally **/ - LUMIERA_THREAD_JOINABLE = 1<<17 + LUMIERA_THREAD_JOINABLE = 1<<9 }; #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 */ LumieraThread -lumiera_thread_run (enum lumiera_thread_class kind, +lumiera_thread_run (int kind, void (*function)(void *), void * arg, const char* purpose, diff --git a/tests/lib/thread-wrapper-join-test.cpp b/tests/lib/thread-wrapper-join-test.cpp index 93257e794..aff2ffab7 100644 --- a/tests/lib/thread-wrapper-join-test.cpp +++ b/tests/lib/thread-wrapper-join-test.cpp @@ -129,6 +129,13 @@ namespace backend { // while the third thread wasn't created at all. } + public: + ThreadWrapperJoin_test() + { lumiera_threadpool_init(); } + + ~ThreadWrapperJoin_test() + { lumiera_threadpool_destroy(); } + }; diff --git a/tests/lib/thread-wrapper-test.cpp b/tests/lib/thread-wrapper-test.cpp index edd9660f1..af8a6f149 100644 --- a/tests/lib/thread-wrapper-test.cpp +++ b/tests/lib/thread-wrapper-test.cpp @@ -104,6 +104,12 @@ namespace backend { ASSERT (sum==checksum); } + public: + ThreadWrapper_test() + { lumiera_threadpool_init(); } + + ~ThreadWrapper_test() + { lumiera_threadpool_destroy(); } };