apr  1.7.0
About: APR (Apache Portable Runtime) project offers software libraries that provide a predictable and consistent interface to underlying platform-specific implementations (APR core library).
  Fossies Dox: apr-1.7.0.tar.bz2  ("inofficial" and yet experimental doxygen-generated source code documentation)  

thread_cond.c
Go to the documentation of this file.
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements. See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License. You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "apr_arch_thread_mutex.h"
18 #include "apr_arch_thread_cond.h"
19 #include "apr_strings.h"
20 #include "apr_portable.h"
21 
23 {
24  struct waiter *w;
26 
27  acquire_sem(cond->lock);
28  delete_sem(cond->lock);
29 
30  return APR_SUCCESS;
31 }
32 
34 {
35  struct waiter_t *w = (struct waiter_t*)
36  apr_palloc(pool, sizeof(struct waiter_t));
37  if (w == NULL)
38  return NULL;
39 
40  w->sem = create_sem(0, "apr conditional waiter");
41  if (w->sem < 0)
42  return NULL;
43 
44  APR_RING_ELEM_INIT(w, link);
45 
46  return w;
47 }
48 
49 APR_DECLARE(apr_status_t) apr_thread_cond_create(apr_thread_cond_t **cond,
51 {
52  apr_thread_cond_t *new_cond;
53  sem_id rv;
54  int i;
55 
56  new_cond = (apr_thread_cond_t *)apr_palloc(pool, sizeof(apr_thread_cond_t));
57 
58  if (new_cond == NULL)
59  return APR_ENOMEM;
60 
61  if ((rv = create_sem(1, "apr conditional lock")) < B_OK)
62  return rv;
63 
64  new_cond->lock = rv;
65  new_cond->pool = pool;
66  APR_RING_INIT(&new_cond->alist, waiter_t, link);
67  APR_RING_INIT(&new_cond->flist, waiter_t, link);
68 
69  for (i=0;i < 10 ;i++) {
70  struct waiter_t *nw = make_waiter(pool);
71  APR_RING_INSERT_TAIL(&new_cond->flist, nw, waiter_t, link);
72  }
73 
74  apr_pool_cleanup_register(new_cond->pool,
75  (void *)new_cond, thread_cond_cleanup,
76  apr_pool_cleanup_null);
77 
78  *cond = new_cond;
79  return APR_SUCCESS;
80 }
81 
82 
85 {
86  struct waiter_t *wait;
87  thread_id cth = find_thread(NULL);
88  apr_status_t rv;
89  int flags = B_RELATIVE_TIMEOUT;
90 
91  /* We must be the owner of the mutex or we can't do this... */
92  if (mutex->owner != cth) {
93  /* What should we return??? */
94  return APR_EINVAL;
95  }
96 
97  acquire_sem(cond->lock);
98  wait = APR_RING_FIRST(&cond->flist);
99  if (wait)
100  APR_RING_REMOVE(wait, link);
101  else
102  wait = make_waiter(cond->pool);
103  APR_RING_INSERT_TAIL(&cond->alist, wait, waiter_t, link);
104  cond->condlock = mutex;
105  release_sem(cond->lock);
106 
107  apr_thread_mutex_unlock(cond->condlock);
108 
109  if (timeout == 0)
110  flags = 0;
111 
112  rv = acquire_sem_etc(wait->sem, 1, flags, timeout);
113 
114  apr_thread_mutex_lock(cond->condlock);
115 
116  if (rv != B_OK) {
117  if (rv == B_TIMED_OUT)
118  return APR_TIMEUP;
119  return rv;
120  }
121 
122  acquire_sem(cond->lock);
123  APR_RING_REMOVE(wait, link);
124  APR_RING_INSERT_TAIL(&cond->flist, wait, waiter_t, link);
125  release_sem(cond->lock);
126 
127  return APR_SUCCESS;
128 }
129 
130 APR_DECLARE(apr_status_t) apr_thread_cond_wait(apr_thread_cond_t *cond,
131  apr_thread_mutex_t *mutex)
132 {
133  return do_wait(cond, mutex, 0);
134 }
135 
136 APR_DECLARE(apr_status_t) apr_thread_cond_timedwait(apr_thread_cond_t *cond,
137  apr_thread_mutex_t *mutex,
139 {
140  return do_wait(cond, mutex, timeout);
141 }
142 
143 APR_DECLARE(apr_status_t) apr_thread_cond_signal(apr_thread_cond_t *cond)
144 {
145  struct waiter_t *wake;
146 
147  acquire_sem(cond->lock);
148  if (!APR_RING_EMPTY(&cond->alist, waiter_t, link)) {
149  wake = APR_RING_FIRST(&cond->alist);
150  APR_RING_REMOVE(wake, link);
151  release_sem(wake->sem);
152  APR_RING_INSERT_TAIL(&cond->flist, wake, waiter_t, link);
153  }
154  release_sem(cond->lock);
155 
156  return APR_SUCCESS;
157 }
158 
159 APR_DECLARE(apr_status_t) apr_thread_cond_broadcast(apr_thread_cond_t *cond)
160 {
161  struct waiter_t *wake;
162 
163  acquire_sem(cond->lock);
164  while (! APR_RING_EMPTY(&cond->alist, waiter_t, link)) {
165  wake = APR_RING_FIRST(&cond->alist);
166  APR_RING_REMOVE(wake, link);
167  release_sem(wake->sem);
168  APR_RING_INSERT_TAIL(&cond->flist, wake, waiter_t, link);
169  }
170  release_sem(cond->lock);
171 
172  return APR_SUCCESS;
173 }
174 
175 APR_DECLARE(apr_status_t) apr_thread_cond_destroy(apr_thread_cond_t *cond)
176 {
177  apr_status_t stat;
178  if ((stat = thread_cond_cleanup(cond)) == APR_SUCCESS) {
179  apr_pool_cleanup_kill(cond->pool, cond, thread_cond_cleanup);
180  return APR_SUCCESS;
181  }
182  return stat;
183 }
184 
185 APR_POOL_IMPLEMENT_ACCESSOR(thread_cond)
186 
pool
const char int apr_pool_t * pool
Definition: apr_cstr.h:82
APR_EINVAL
#define APR_EINVAL
Definition: apr_errno.h:711
apr_thread_cond_t::lock
sem_id lock
Definition: apr_arch_thread_cond.h:36
data
void * data
Definition: apr_file_io.h:861
thread_cond_cleanup
static apr_status_t thread_cond_cleanup(void *data)
Definition: thread_cond.c:22
APR_RING_INSERT_TAIL
#define APR_RING_INSERT_TAIL(hp, nep, elem, link)
Definition: apr_ring.h:322
apr_thread_cond_t
Definition: apr_arch_thread_cond.h:34
timeout
IN ULONG IN INT timeout
Definition: apr_arch_misc.h:477
apr_thread_mutex_t
Definition: apr_arch_thread_mutex.h:28
apr_strings.h
APR Strings library.
do_wait
static apr_status_t do_wait(apr_thread_cond_t *cond, apr_thread_mutex_t *mutex, apr_interval_time_t timeout)
Definition: thread_cond.c:83
apr_thread_mutex_t::owner
apr_os_thread_t owner
Definition: apr_arch_thread_mutex.h:37
apr_portable.h
APR Portability Routines.
APR_RING_ELEM_INIT
#define APR_RING_ELEM_INIT(ep, link)
Definition: apr_ring.h:212
APR_DECLARE
APR_DECLARE(apr_status_t)
Definition: thread_cond.c:49
make_waiter
static struct waiter_t * make_waiter(apr_pool_t *pool)
Definition: thread_cond.c:33
apr_thread_cond_t::condlock
apr_thread_mutex_t * condlock
Definition: apr_arch_thread_cond.h:37
APR_TIMEUP
#define APR_TIMEUP
Definition: apr_errno.h:450
APR_RING_INIT
#define APR_RING_INIT(hp, elem, link)
Definition: apr_ring.h:192
apr_interval_time_t
apr_int64_t apr_interval_time_t
Definition: apr_time.h:55
waiter_t
Definition: apr_arch_thread_cond.h:29
apr_pool_t
Definition: apr_pools.c:577
APR_ENOMEM
#define APR_ENOMEM
Definition: apr_errno.h:683
apr_status_t
int apr_status_t
Definition: apr_errno.h:44
APR_RING_EMPTY
#define APR_RING_EMPTY(hp, elem, link)
Definition: apr_ring.h:204
APR_SUCCESS
#define APR_SUCCESS
Definition: apr_errno.h:225
APR_RING_REMOVE
#define APR_RING_REMOVE(ep, link)
Definition: apr_ring.h:377
flags
const char apr_ssize_t int flags
Definition: apr_encode.h:162
APR_RING_FIRST
#define APR_RING_FIRST(hp)
Definition: apr_ring.h:166
waiter_t::sem
sem_id sem
Definition: apr_arch_thread_cond.h:31
apr_thread_cond_t::pool
apr_pool_t * pool
Definition: apr_arch_thread_cond.h:35
APR_POOL_IMPLEMENT_ACCESSOR
#define APR_POOL_IMPLEMENT_ACCESSOR(type)
Definition: apr_pools.h:91