Merge commit '6f07e4eedc6b624b1f9ae1004ad3e6a77027e028' into second-tp-attempt

Conflicts:
	src/backend/threads.c
This commit is contained in:
Michael Ploujnikov 2010-01-20 21:41:14 -05:00
commit fc15a2ac2c
8 changed files with 60 additions and 69 deletions

View file

@ -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)

View file

@ -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 ();
} }

View file

@ -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;
} }
} }

View file

@ -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;

View file

@ -92,15 +92,15 @@ 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);
} while (t->state != LUMIERA_THREADSTATE_SHUTDOWN);
// SHUTDOWN state
if (t->kind & LUMIERA_THREAD_JOINABLE) if (t->kind & LUMIERA_THREAD_JOINABLE)
{ {
@ -108,10 +108,15 @@ thread_loop (void* thread)
/* move error state to data the other thread will it pick up from there */ /* move error state to data the other thread will it pick up from there */
t->arguments = (void*)lumiera_error (); t->arguments = (void*)lumiera_error ();
t->state = LUMIERA_THREADSTATE_ZOMBIE; t->state = LUMIERA_THREADSTATE_ZOMBIE;
LUMIERA_CONDITION_SIGNAL;
LUMIERA_CONDITION_WAIT (t->state == LUMIERA_THREADSTATE_JOINED); LUMIERA_CONDITION_WAIT (t->state == LUMIERA_THREADSTATE_JOINED);
INFO (threads, "Thread joined"); INFO (threads, "Thread joined");
} }
} while (t->state != LUMIERA_THREADSTATE_SHUTDOWN);
// SHUTDOWN state
INFO (threads, "Thread Shutdown"); INFO (threads, "Thread Shutdown");
} }
TODO ("no error must be pending here, else do app shutdown"); TODO ("no error must be pending here, else do app 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)");

View file

@ -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,

View file

@ -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(); }
}; };

View file

@ -104,6 +104,12 @@ namespace backend {
ASSERT (sum==checksum); ASSERT (sum==checksum);
} }
public:
ThreadWrapper_test()
{ lumiera_threadpool_init(); }
~ThreadWrapper_test()
{ lumiera_threadpool_destroy(); }
}; };