You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@apr.apache.org by dr...@apache.org on 2001/12/11 17:54:38 UTC

cvs commit: apr/include/arch/beos thread_cond.h

dreid       01/12/11 08:54:38

  Modified:    locks/beos thread_cond.c
               include/arch/beos thread_cond.h
  Log:
  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.
  
  Revision  Changes    Path
  1.4       +119 -7    apr/locks/beos/thread_cond.c
  
  Index: thread_cond.c
  ===================================================================
  RCS file: /home/cvs/apr/locks/beos/thread_cond.c,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- thread_cond.c	2001/10/12 01:05:02	1.3
  +++ thread_cond.c	2001/12/11 16:54:38	1.4
  @@ -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)
  +{
  +    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)
   {
  -    return APR_ENOTIMPL;
  +    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)
  
  
  
  1.2       +11 -0     apr/include/arch/beos/thread_cond.h
  
  Index: thread_cond.h
  ===================================================================
  RCS file: /home/cvs/apr/include/arch/beos/thread_cond.h,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- thread_cond.h	2001/09/13 01:04:22	1.1
  +++ thread_cond.h	2001/12/11 16:54:38	1.2
  @@ -63,8 +63,19 @@
   #include "apr_lib.h"
   #include "apr_portable.h"
   
  +struct waiter {
  +    apr_pool_t *pool;
  +    sem_id sem;
  +    struct waiter *next;
  +};
  + 
   struct apr_thread_cond_t {
       apr_pool_t *pool;
  +    sem_id lock;
  +    apr_thread_mutex_t *condlock;
  +    thread_id owner;
  +    struct waiter *list;
  +    struct waiter *tail;
   };
   
   #endif  /* THREAD_COND_H */