diff options
author | David Reid <dreid@apache.org> | 2001-12-11 16:54:38 +0000 |
---|---|---|
committer | David Reid <dreid@apache.org> | 2001-12-11 16:54:38 +0000 |
commit | eb502c4e4fa57fe36044ab568dffd16dbe23e57d (patch) | |
tree | 266d7166aa01675a2df3209918e073f3d291f06f /locks/beos | |
parent | 7b90d0a926c7fe2b6d531444807af0070b44b883 (diff) | |
download | apr-eb502c4e4fa57fe36044ab568dffd16dbe23e57d.tar.gz |
The first pass at adding conditionals for BeOS. These are heavily based
on the email's between Victor and Aaron and the pseudo code that resulted.
It's not perfect, but passes all the tests in testlock, so at least it's
a start. Hopefully more eyes will see the problems. It'd also be good to
try and improve the test suite for conditionals.
git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@62623 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'locks/beos')
-rw-r--r-- | locks/beos/thread_cond.c | 126 |
1 files changed, 119 insertions, 7 deletions
diff --git a/locks/beos/thread_cond.c b/locks/beos/thread_cond.c index 30a4a25c4..daaac4e19 100644 --- a/locks/beos/thread_cond.c +++ b/locks/beos/thread_cond.c @@ -61,38 +61,150 @@ #include "apr_strings.h" #include "apr_portable.h" +static apr_status_t thread_cond_cleanup(void *data) +{ + struct waiter *w; + apr_thread_cond_t *cond = (apr_thread_cond_t *)data; + + acquire_sem(cond->lock); + /* Go through waiters list and delete the sem's so we don't leak. */ + while (cond->list) { + w = cond->list; + cond->list = w->next; + delete_sem(w->sem); + } + delete_sem(cond->lock); + return APR_SUCCESS; +} + APR_DECLARE(apr_status_t) apr_thread_cond_create(apr_thread_cond_t **cond, apr_pool_t *pool) { - return APR_ENOTIMPL; + apr_thread_cond_t *new_cond; + sem_id rv; + + new_cond = (apr_thread_cond_t *)apr_palloc(pool, sizeof(apr_thread_cond_t)); + + if (new_cond == NULL) + return APR_ENOMEM; + + if ((rv = create_sem(1, "apr conditional lock")) < B_OK) + return rv; + + new_cond->lock = rv; + new_cond->pool = pool; + new_cond->list = NULL; + + apr_pool_cleanup_register(new_cond->pool, + (void *)new_cond, thread_cond_cleanup, + apr_pool_cleanup_null); + + *cond = new_cond; + return APR_SUCCESS; +} + +static apr_status_t do_wait(apr_thread_cond_t *cond, apr_thread_mutex_t *mutex, + int timeout) +{ + struct waiter *wait = apr_palloc(cond->pool, sizeof(struct waiter)); + thread_id cth = find_thread(NULL); + apr_status_t rv; + + if (!wait) + return APR_ENOMEM; + + if (cond->owner > 0 && cth != cond->owner) { + /* What should we return??? */ + return APR_EINVAL; + } + + wait->sem = create_sem(0, "apr conditional waiter"); + wait->next = NULL; + wait->pool = cond->pool; + cond->condlock = mutex; + + acquire_sem(cond->lock); + cond->owner = -1; + + if (!cond->list) + cond->list = wait; + else + cond->tail->next = wait; + cond->tail = wait; + + release_sem(cond->lock); + + apr_thread_mutex_unlock(cond->condlock); + + rv = acquire_sem_etc(wait->sem, 1, B_RELATIVE_TIMEOUT, timeout); + if (rv != B_OK) + if (rv == B_TIMED_OUT) + return APR_TIMEUP; + return rv; + + apr_thread_mutex_lock(cond->condlock); + + acquire_sem(cond->lock); + cond->owner = find_thread(NULL); + release_sem(cond->lock); + + delete_sem(wait->sem); + + return APR_SUCCESS; } APR_DECLARE(apr_status_t) apr_thread_cond_wait(apr_thread_cond_t *cond, apr_thread_mutex_t *mutex) { - return APR_ENOTIMPL; + return do_wait(cond, mutex, 0); } APR_DECLARE(apr_status_t) apr_thread_cond_timedwait(apr_thread_cond_t *cond, apr_thread_mutex_t *mutex, - apr_interval_time_t timeout){ - return APR_ENOTIMPL; + apr_interval_time_t timeout) +{ + return do_wait(cond, mutex, timeout); } APR_DECLARE(apr_status_t) apr_thread_cond_signal(apr_thread_cond_t *cond) { - return APR_ENOTIMPL; + struct waiter *wake; + + acquire_sem(cond->lock); + if (cond->list) { + wake = cond->list; + cond->list = wake->next; + release_sem(wake->sem); + } + release_sem(cond->lock); + + return APR_SUCCESS; } APR_DECLARE(apr_status_t) apr_thread_cond_broadcast(apr_thread_cond_t *cond) { - return APR_ENOTIMPL; + struct waiter *wake; + + acquire_sem(cond->lock); + while (cond->list) { + wake = cond->list; + cond->list = wake->next; + release_sem(wake->sem); + } + release_sem(cond->lock); + + return APR_SUCCESS; } APR_DECLARE(apr_status_t) apr_thread_cond_destroy(apr_thread_cond_t *cond) { - return APR_ENOTIMPL; + apr_status_t stat; + if ((stat = thread_cond_cleanup(cond)) == APR_SUCCESS) { + apr_pool_cleanup_kill(cond->pool, cond, thread_cond_cleanup); + return APR_SUCCESS; + } + return stat; } APR_POOL_IMPLEMENT_ACCESSOR(thread_cond) |