summaryrefslogtreecommitdiff
path: root/locks/beos
diff options
context:
space:
mode:
authorDavid Reid <dreid@apache.org>2001-12-11 16:54:38 +0000
committerDavid Reid <dreid@apache.org>2001-12-11 16:54:38 +0000
commiteb502c4e4fa57fe36044ab568dffd16dbe23e57d (patch)
tree266d7166aa01675a2df3209918e073f3d291f06f /locks/beos
parent7b90d0a926c7fe2b6d531444807af0070b44b883 (diff)
downloadapr-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.c126
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)