recondition to condition,

remove the mutex from the pool
rename park to release :P
This commit is contained in:
Christian Thaeter 2009-12-24 01:54:49 +01:00
parent 6b4415d8fa
commit 88195087d6
5 changed files with 57 additions and 61 deletions

View file

@ -57,12 +57,10 @@ lumiera_threadpool_init()
//TODO: configure each pools' pthread_attrs appropriately
pthread_attr_init (&threadpool.pool[i].pthread_attrs);
// cehteh prefers that threads are joinable by default
//pthread_attr_setdetachstate (&threadpool.pool[i].pthread_attrs, PTHREAD_CREATE_DETACHED);
// cehteh says that threads must be joinable
//cancel...
lumiera_mutex_init(&threadpool.pool[i].lock,"pool of threads", &NOBUG_FLAG(threadpool));
lumiera_reccondition_init (&threadpool.pool[i].signal, "thread-signal", &NOBUG_FLAG(threadpool));
lumiera_condition_init (&threadpool.pool[i].sync, "threadpool", &NOBUG_FLAG(cond_sync));
}
}
@ -74,7 +72,7 @@ lumiera_threadpool_destroy(void)
for (int i = 0; i < LUMIERA_THREADCLASS_COUNT; ++i)
{
TRACE (threadpool, "destroying individual pool #%d", i);
LUMIERA_MUTEX_SECTION (threadpool, &threadpool.pool[i].lock)
LUMIERA_CONDITION_SECTION (threadpool, &threadpool.pool[i].sync)
{
REQUIRE (0 == threadpool.pool[i].working_thread_count, "%d threads are running", threadpool.pool[i].working_thread_count);
// TODO need to have a stronger assertion that no threads are really running because they will not even be in the list
@ -84,9 +82,8 @@ lumiera_threadpool_destroy(void)
lumiera_thread_delete((LumieraThread)t);
}
}
ECHO ("destroying the pool mutex");
lumiera_mutex_destroy (&threadpool.pool[i].lock, &NOBUG_FLAG (threadpool));
ECHO ("pool mutex destroyed");
lumiera_condition_destroy (&threadpool.pool[i].sync, &NOBUG_FLAG (cond_sync));
pthread_attr_destroy (&threadpool.pool[i].pthread_attrs);
}
}
@ -100,16 +97,17 @@ lumiera_threadpool_acquire_thread(enum lumiera_thread_class kind,
TRACE(threadpool);
LumieraThread ret = NULL;
REQUIRE (kind < LUMIERA_THREADCLASS_COUNT, "unknown pool kind specified: %d", kind);
LUMIERA_RECCONDITION_SECTION (threadpool, &threadpool.pool[kind].signal)
{
if (llist_is_empty (&threadpool.pool[kind].list))
{
ret = lumiera_thread_new (kind, purpose, flag,
&threadpool.pool[kind].pthread_attrs);
threadpool.pool[kind].idle_thread_count++;
ENSURE (ret, "did not create a valid thread");
LUMIERA_RECCONDITION_WAIT (!llist_is_empty (&threadpool.pool[kind].list));
LUMIERA_CONDITION_SECTION (threadpool, &threadpool.pool[kind].sync)
{
if (llist_is_empty (&threadpool.pool[kind].list))
{
ret = lumiera_thread_new (kind, purpose, flag,
&threadpool.pool[kind].pthread_attrs);
ENSURE (ret, "did not create a valid thread");
TODO("no error handling but let the resourcecollector do, no need for return the thread");
LUMIERA_CONDITION_WAIT (!llist_is_empty (&threadpool.pool[kind].list));
}
// use an existing thread, pick the first one
// remove it from the pool's list
@ -129,7 +127,7 @@ lumiera_threadpool_acquire_thread(enum lumiera_thread_class kind,
// TODO: rename to lumiera_threadpool_park_thread
void
lumiera_threadpool_park_thread(LumieraThread thread)
lumiera_threadpool_release_thread(LumieraThread thread)
{
TRACE(threadpool);
REQUIRE (thread, "invalid thread given");
@ -137,20 +135,22 @@ lumiera_threadpool_park_thread(LumieraThread thread)
REQUIRE (thread->state != LUMIERA_THREADSTATE_IDLE, "trying to park an already idle thread");
LUMIERA_RECCONDITION_SECTION (threadpool, &threadpool.pool[thread->kind].signal)
LUMIERA_CONDITION_SECTION (threadpool, &threadpool.pool[thread->kind].sync)
{
thread->state = LUMIERA_THREADSTATE_IDLE;
REQUIRE (llist_is_single(&thread->node), "thread already belongs to some list");
REQUIRE (!llist_is_empty(&thread->node), "thread already belongs to some list");
llist_insert_head(&threadpool.pool[thread->kind].list, &thread->node);
threadpool.pool[thread->kind].working_thread_count--;
threadpool.pool[thread->kind].idle_thread_count++; // cheaper than using llist_count
ENSURE (threadpool.pool[thread->kind].idle_thread_count ==
llist_count(&threadpool.pool[thread->kind].list),
"idle thread count %d is wrong, should be %d",
threadpool.pool[thread->kind].idle_thread_count,
llist_count(&threadpool.pool[thread->kind].list));
// REQUIRE (!llist_is_empty (&threadpool.pool[thread->kind].list), "thread pool is still empty after insertion");
LUMIERA_RECCONDITION_BROADCAST;
threadpool.pool[thread->kind].working_thread_count--;
threadpool.pool[thread->kind].idle_thread_count++; // cheaper than using llist_count
ENSURE (threadpool.pool[thread->kind].idle_thread_count ==
llist_count(&threadpool.pool[thread->kind].list),
"idle thread count %d is wrong, should be %d",
threadpool.pool[thread->kind].idle_thread_count,
llist_count(&threadpool.pool[thread->kind].list));
REQUIRE (!llist_is_empty (&threadpool.pool[thread->kind].list), "thread pool is still empty after insertion");
LUMIERA_CONDITION_BROADCAST;
}
}

View file

@ -23,9 +23,8 @@
#define LUMIERA_THREADPOOL_H
//TODO: Support library includes//
#include "lib/reccondition.h"
#include "lib/condition.h"
#include "lib/llist.h"
#include "lib/mutex.h"
//TODO: Forward declarations//
@ -60,7 +59,7 @@ lumiera_threadpool_acquire_thread(enum lumiera_thread_class kind,
* This function doesn't need to be accessible outside of the threadpool implementation.
*/
void
lumiera_threadpool_park_thread(LumieraThread thread);
lumiera_threadpool_release_thread(LumieraThread thread);
typedef struct lumiera_threadpool_struct lumiera_threadpool;
typedef lumiera_threadpool* LumieraThreadpool;
@ -70,11 +69,10 @@ struct lumiera_threadpool_struct
struct
{
llist list;
lumiera_mutex lock;
unsigned working_thread_count;
unsigned idle_thread_count;
pthread_attr_t pthread_attrs;
lumiera_reccondition signal;
lumiera_condition sync;
} pool[LUMIERA_THREADCLASS_COUNT];
};

View file

@ -22,7 +22,6 @@
//TODO: Support library includes//
#include "include/logging.h"
#include "lib/mutex.h"
#include "lib/safeclib.h"
@ -64,7 +63,7 @@ struct lumiera_thread_mockup
{
void (*fn)(void*);
void* arg;
LumieraReccondition finished;
LumieraCondition finished;
};
static void* thread_loop (void* thread)
@ -73,21 +72,20 @@ static void* thread_loop (void* thread)
LumieraThread t = (LumieraThread)thread;
pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL);
REQUIRE (t, "thread does not exist");
ECHO ("entering section 1");
// this seems to deadlock unexpectedly:
LUMIERA_RECCONDITION_SECTION (threads, &t->signal)
LUMIERA_CONDITION_SECTION (threads, &t->signal)
{
do {
// 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);
lumiera_threadpool_park_thread(t);
LUMIERA_RECCONDITION_WAIT(t->state != LUMIERA_THREADSTATE_IDLE);
} while (t->state != LUMIERA_THREADSTATE_SHUTDOWN);
// SHUTDOWN state
@ -117,9 +115,9 @@ lumiera_thread_run (enum lumiera_thread_class kind,
// and let it really run (signal the condition var, the thread waits on it)
self->state = LUMIERA_THREADSTATE_WAKEUP;
ECHO ("entering section 2");
LUMIERA_RECCONDITION_SECTION(threads, &self->signal)
LUMIERA_RECCONDITION_BROADCAST;
LUMIERA_CONDITION_SECTION(threads, &self->signal)
LUMIERA_CONDITION_SIGNAL;
// NOTE: example only, add solid error handling!
@ -142,7 +140,7 @@ lumiera_thread_new (enum lumiera_thread_class kind,
LumieraThread self = lumiera_malloc (sizeof (*self));
llist_init(&self->node);
lumiera_reccondition_init (&self->signal, "thread-control", flag);
lumiera_condition_init (&self->signal, "thread-control", flag);
self->kind = kind;
self->state = LUMIERA_THREADSTATE_STARTUP;
self->function = NULL;
@ -170,20 +168,20 @@ lumiera_thread_destroy (LumieraThread self)
// get the pthread out of the processing loop
// need to signal to the thread that it should start quitting
// should this be within the section?
LUMIERA_RECCONDITION_SECTION(threads, &self->signal)
LUMIERA_CONDITION_SECTION(threads, &self->signal)
{
REQUIRE (self->state == LUMIERA_THREADSTATE_IDLE, "trying to delete a thread in state other than IDLE (%s)", lumiera_threadstate_names[self->state]);
self->state = LUMIERA_THREADSTATE_SHUTDOWN;
self->function = NULL;
self->arguments = NULL;
LUMIERA_RECCONDITION_SIGNAL;
LUMIERA_CONDITION_SIGNAL;
}
int error = pthread_join(self->id, NULL);
ENSURE (0 == error, "pthread_join returned %d:%s", error, strerror(error));
// condition has to be destroyed after joining with the thread
lumiera_reccondition_destroy (&self->signal, &NOBUG_FLAG(threads));
lumiera_condition_destroy (&self->signal, &NOBUG_FLAG(threads));
return self;
}

View file

@ -23,7 +23,7 @@
#define LUMIERA_THREADS_H
//TODO: Support library includes//
#include "lib/reccondition.h"
#include "lib/condition.h"
//TODO: Forward declarations//
@ -132,7 +132,7 @@ struct lumiera_thread_struct
// void* arg;
pthread_t id;
// TODO: maybe this condition variable should be renamed when we have a better understanding of how it will be used
lumiera_reccondition signal; // control signal, state change signal
lumiera_condition signal; // control signal, state change signal
// the following member could have been called "class" except that it would conflict with C++ keyword
// as consequence, it's been decided to leave the type name containing the word "class",
// while all members/variables called "kind"

View file

@ -47,15 +47,15 @@ void threadfn(void* blah)
void threadsyncfn(void* blah)
{
struct timespec wait = {0,200000000};
LumieraReccondition sync = (LumieraReccondition) blah;
LumieraCondition sync = (LumieraCondition) blah;
ECHO ("thread starting up %s", NOBUG_THREAD_ID_GET);
LUMIERA_RECCONDITION_SECTION(cond_sync, sync)
LUMIERA_CONDITION_SECTION(cond_sync, sync)
{
ECHO ("send startup signal %s", NOBUG_THREAD_ID_GET);
LUMIERA_RECCONDITION_SIGNAL;
LUMIERA_CONDITION_SIGNAL;
ECHO ("wait for trigger %s", NOBUG_THREAD_ID_GET);
LUMIERA_RECCONDITION_WAIT(1);
LUMIERA_CONDITION_WAIT(1);
}
ECHO ("thread running %s", NOBUG_THREAD_ID_GET);
@ -101,10 +101,10 @@ TEST ("simple_thread")
TEST ("thread_synced")
{
lumiera_reccondition cnd;
lumiera_reccondition_init (&cnd, "threadsync", &NOBUG_FLAG(NOBUG_ON));
lumiera_condition cnd;
lumiera_condition_init (&cnd, "threadsync", &NOBUG_FLAG(NOBUG_ON));
LUMIERA_RECCONDITION_SECTION(cond_sync, &cnd)
LUMIERA_CONDITION_SECTION(cond_sync, &cnd)
{
ECHO ("main before thread %s", NOBUG_THREAD_ID_GET);
@ -115,17 +115,17 @@ TEST ("thread_synced")
NULL);
ECHO ("main wait for thread being ready %s", NOBUG_THREAD_ID_GET);
LUMIERA_RECCONDITION_WAIT(1);
LUMIERA_CONDITION_WAIT(1);
ECHO ("main trigger thread %s", NOBUG_THREAD_ID_GET);
LUMIERA_RECCONDITION_SIGNAL;
LUMIERA_CONDITION_SIGNAL;
ECHO ("wait for thread end %s", NOBUG_THREAD_ID_GET);
LUMIERA_RECCONDITION_WAIT(1);
LUMIERA_CONDITION_WAIT(1);
ECHO ("thread ended %s", NOBUG_THREAD_ID_GET);
}
lumiera_reccondition_destroy (&cnd, &NOBUG_FLAG(NOBUG_ON));
lumiera_condition_destroy (&cnd, &NOBUG_FLAG(NOBUG_ON));
}