1*cc02d7e2SAndroid Build Coastguard Worker /* 2*cc02d7e2SAndroid Build Coastguard Worker * 3*cc02d7e2SAndroid Build Coastguard Worker * Copyright 2015 gRPC authors. 4*cc02d7e2SAndroid Build Coastguard Worker * 5*cc02d7e2SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 6*cc02d7e2SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 7*cc02d7e2SAndroid Build Coastguard Worker * You may obtain a copy of the License at 8*cc02d7e2SAndroid Build Coastguard Worker * 9*cc02d7e2SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 10*cc02d7e2SAndroid Build Coastguard Worker * 11*cc02d7e2SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 12*cc02d7e2SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 13*cc02d7e2SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*cc02d7e2SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 15*cc02d7e2SAndroid Build Coastguard Worker * limitations under the License. 16*cc02d7e2SAndroid Build Coastguard Worker * 17*cc02d7e2SAndroid Build Coastguard Worker */ 18*cc02d7e2SAndroid Build Coastguard Worker 19*cc02d7e2SAndroid Build Coastguard Worker #ifndef GRPC_SUPPORT_SYNC_H 20*cc02d7e2SAndroid Build Coastguard Worker #define GRPC_SUPPORT_SYNC_H 21*cc02d7e2SAndroid Build Coastguard Worker 22*cc02d7e2SAndroid Build Coastguard Worker /* Platform-specific type declarations of gpr_mu and gpr_cv. */ 23*cc02d7e2SAndroid Build Coastguard Worker #include <grpc/support/port_platform.h> 24*cc02d7e2SAndroid Build Coastguard Worker #include <grpc/support/time.h> /* for gpr_timespec */ 25*cc02d7e2SAndroid Build Coastguard Worker 26*cc02d7e2SAndroid Build Coastguard Worker #ifdef __cplusplus 27*cc02d7e2SAndroid Build Coastguard Worker extern "C" { 28*cc02d7e2SAndroid Build Coastguard Worker #endif 29*cc02d7e2SAndroid Build Coastguard Worker 30*cc02d7e2SAndroid Build Coastguard Worker /** Synchronization primitives for GPR. 31*cc02d7e2SAndroid Build Coastguard Worker 32*cc02d7e2SAndroid Build Coastguard Worker The type gpr_mu provides a non-reentrant mutex (lock). 33*cc02d7e2SAndroid Build Coastguard Worker 34*cc02d7e2SAndroid Build Coastguard Worker The type gpr_cv provides a condition variable. 35*cc02d7e2SAndroid Build Coastguard Worker 36*cc02d7e2SAndroid Build Coastguard Worker The type gpr_once provides for one-time initialization. 37*cc02d7e2SAndroid Build Coastguard Worker 38*cc02d7e2SAndroid Build Coastguard Worker The type gpr_event provides one-time-setting, reading, and 39*cc02d7e2SAndroid Build Coastguard Worker waiting of a void*, with memory barriers. 40*cc02d7e2SAndroid Build Coastguard Worker 41*cc02d7e2SAndroid Build Coastguard Worker The type gpr_refcount provides an object reference counter, 42*cc02d7e2SAndroid Build Coastguard Worker with memory barriers suitable to control 43*cc02d7e2SAndroid Build Coastguard Worker object lifetimes. 44*cc02d7e2SAndroid Build Coastguard Worker 45*cc02d7e2SAndroid Build Coastguard Worker The type gpr_stats_counter provides an atomic statistics counter. It 46*cc02d7e2SAndroid Build Coastguard Worker provides no memory barriers. 47*cc02d7e2SAndroid Build Coastguard Worker */ 48*cc02d7e2SAndroid Build Coastguard Worker 49*cc02d7e2SAndroid Build Coastguard Worker #include <grpc/support/sync_generic.h> // IWYU pragma: export 50*cc02d7e2SAndroid Build Coastguard Worker 51*cc02d7e2SAndroid Build Coastguard Worker #if defined(GPR_CUSTOM_SYNC) 52*cc02d7e2SAndroid Build Coastguard Worker #include <grpc/support/sync_custom.h> // IWYU pragma: export 53*cc02d7e2SAndroid Build Coastguard Worker #elif defined(GPR_ABSEIL_SYNC) 54*cc02d7e2SAndroid Build Coastguard Worker #include <grpc/support/sync_abseil.h> // IWYU pragma: export 55*cc02d7e2SAndroid Build Coastguard Worker #elif defined(GPR_POSIX_SYNC) 56*cc02d7e2SAndroid Build Coastguard Worker #include <grpc/support/sync_posix.h> // IWYU pragma: export 57*cc02d7e2SAndroid Build Coastguard Worker #elif defined(GPR_WINDOWS) 58*cc02d7e2SAndroid Build Coastguard Worker #include <grpc/support/sync_windows.h> // IWYU pragma: export 59*cc02d7e2SAndroid Build Coastguard Worker #else 60*cc02d7e2SAndroid Build Coastguard Worker #error Unable to determine platform for sync 61*cc02d7e2SAndroid Build Coastguard Worker #endif 62*cc02d7e2SAndroid Build Coastguard Worker 63*cc02d7e2SAndroid Build Coastguard Worker /** --- Mutex interface --- 64*cc02d7e2SAndroid Build Coastguard Worker 65*cc02d7e2SAndroid Build Coastguard Worker At most one thread may hold an exclusive lock on a mutex at any given time. 66*cc02d7e2SAndroid Build Coastguard Worker Actions taken by a thread that holds a mutex exclusively happen after 67*cc02d7e2SAndroid Build Coastguard Worker actions taken by all previous holders of the mutex. Variables of type 68*cc02d7e2SAndroid Build Coastguard Worker gpr_mu are uninitialized when first declared. */ 69*cc02d7e2SAndroid Build Coastguard Worker 70*cc02d7e2SAndroid Build Coastguard Worker /** Initialize *mu. Requires: *mu uninitialized. */ 71*cc02d7e2SAndroid Build Coastguard Worker GPRAPI void gpr_mu_init(gpr_mu* mu); 72*cc02d7e2SAndroid Build Coastguard Worker 73*cc02d7e2SAndroid Build Coastguard Worker /** Cause *mu no longer to be initialized, freeing any memory in use. Requires: 74*cc02d7e2SAndroid Build Coastguard Worker *mu initialized; no other concurrent operation on *mu. */ 75*cc02d7e2SAndroid Build Coastguard Worker GPRAPI void gpr_mu_destroy(gpr_mu* mu); 76*cc02d7e2SAndroid Build Coastguard Worker 77*cc02d7e2SAndroid Build Coastguard Worker /** Wait until no thread has a lock on *mu, cause the calling thread to own an 78*cc02d7e2SAndroid Build Coastguard Worker exclusive lock on *mu, then return. May block indefinitely or crash if the 79*cc02d7e2SAndroid Build Coastguard Worker calling thread has a lock on *mu. Requires: *mu initialized. */ 80*cc02d7e2SAndroid Build Coastguard Worker GPRAPI void gpr_mu_lock(gpr_mu* mu); 81*cc02d7e2SAndroid Build Coastguard Worker 82*cc02d7e2SAndroid Build Coastguard Worker /** Release an exclusive lock on *mu held by the calling thread. Requires: *mu 83*cc02d7e2SAndroid Build Coastguard Worker initialized; the calling thread holds an exclusive lock on *mu. */ 84*cc02d7e2SAndroid Build Coastguard Worker GPRAPI void gpr_mu_unlock(gpr_mu* mu); 85*cc02d7e2SAndroid Build Coastguard Worker 86*cc02d7e2SAndroid Build Coastguard Worker /** Without blocking, attempt to acquire an exclusive lock on *mu for the 87*cc02d7e2SAndroid Build Coastguard Worker calling thread, then return non-zero iff success. Fail, if any thread holds 88*cc02d7e2SAndroid Build Coastguard Worker the lock; succeeds with high probability if no thread holds the lock. 89*cc02d7e2SAndroid Build Coastguard Worker Requires: *mu initialized. */ 90*cc02d7e2SAndroid Build Coastguard Worker GPRAPI int gpr_mu_trylock(gpr_mu* mu); 91*cc02d7e2SAndroid Build Coastguard Worker 92*cc02d7e2SAndroid Build Coastguard Worker /** --- Condition variable interface --- 93*cc02d7e2SAndroid Build Coastguard Worker 94*cc02d7e2SAndroid Build Coastguard Worker A while-loop should be used with gpr_cv_wait() when waiting for conditions 95*cc02d7e2SAndroid Build Coastguard Worker to become true. See the example below. Variables of type gpr_cv are 96*cc02d7e2SAndroid Build Coastguard Worker uninitialized when first declared. */ 97*cc02d7e2SAndroid Build Coastguard Worker 98*cc02d7e2SAndroid Build Coastguard Worker /** Initialize *cv. Requires: *cv uninitialized. */ 99*cc02d7e2SAndroid Build Coastguard Worker GPRAPI void gpr_cv_init(gpr_cv* cv); 100*cc02d7e2SAndroid Build Coastguard Worker 101*cc02d7e2SAndroid Build Coastguard Worker /** Cause *cv no longer to be initialized, freeing any memory in use. Requires: 102*cc02d7e2SAndroid Build Coastguard Worker *cv initialized; no other concurrent operation on *cv.*/ 103*cc02d7e2SAndroid Build Coastguard Worker GPRAPI void gpr_cv_destroy(gpr_cv* cv); 104*cc02d7e2SAndroid Build Coastguard Worker 105*cc02d7e2SAndroid Build Coastguard Worker /** Atomically release *mu and wait on *cv. When the calling thread is woken 106*cc02d7e2SAndroid Build Coastguard Worker from *cv or the deadline abs_deadline is exceeded, execute gpr_mu_lock(mu) 107*cc02d7e2SAndroid Build Coastguard Worker and return whether the deadline was exceeded. Use 108*cc02d7e2SAndroid Build Coastguard Worker abs_deadline==gpr_inf_future for no deadline. abs_deadline can be either 109*cc02d7e2SAndroid Build Coastguard Worker an absolute deadline, or a GPR_TIMESPAN. May return even when not 110*cc02d7e2SAndroid Build Coastguard Worker woken explicitly. Requires: *mu and *cv initialized; the calling thread 111*cc02d7e2SAndroid Build Coastguard Worker holds an exclusive lock on *mu. */ 112*cc02d7e2SAndroid Build Coastguard Worker GPRAPI int gpr_cv_wait(gpr_cv* cv, gpr_mu* mu, gpr_timespec abs_deadline); 113*cc02d7e2SAndroid Build Coastguard Worker 114*cc02d7e2SAndroid Build Coastguard Worker /** If any threads are waiting on *cv, wake at least one. 115*cc02d7e2SAndroid Build Coastguard Worker Clients may treat this as an optimization of gpr_cv_broadcast() 116*cc02d7e2SAndroid Build Coastguard Worker for use in the case where waking more than one waiter is not useful. 117*cc02d7e2SAndroid Build Coastguard Worker Requires: *cv initialized. */ 118*cc02d7e2SAndroid Build Coastguard Worker GPRAPI void gpr_cv_signal(gpr_cv* cv); 119*cc02d7e2SAndroid Build Coastguard Worker 120*cc02d7e2SAndroid Build Coastguard Worker /** Wake all threads waiting on *cv. Requires: *cv initialized. */ 121*cc02d7e2SAndroid Build Coastguard Worker GPRAPI void gpr_cv_broadcast(gpr_cv* cv); 122*cc02d7e2SAndroid Build Coastguard Worker 123*cc02d7e2SAndroid Build Coastguard Worker /** --- One-time initialization --- 124*cc02d7e2SAndroid Build Coastguard Worker 125*cc02d7e2SAndroid Build Coastguard Worker gpr_once must be declared with static storage class, and initialized with 126*cc02d7e2SAndroid Build Coastguard Worker GPR_ONCE_INIT. e.g., 127*cc02d7e2SAndroid Build Coastguard Worker static gpr_once once_var = GPR_ONCE_INIT; */ 128*cc02d7e2SAndroid Build Coastguard Worker 129*cc02d7e2SAndroid Build Coastguard Worker /** Ensure that (*init_function)() has been called exactly once (for the 130*cc02d7e2SAndroid Build Coastguard Worker specified gpr_once instance) and then return. 131*cc02d7e2SAndroid Build Coastguard Worker If multiple threads call gpr_once() on the same gpr_once instance, one of 132*cc02d7e2SAndroid Build Coastguard Worker them will call (*init_function)(), and the others will block until that call 133*cc02d7e2SAndroid Build Coastguard Worker finishes.*/ 134*cc02d7e2SAndroid Build Coastguard Worker GPRAPI void gpr_once_init(gpr_once* once, void (*init_function)(void)); 135*cc02d7e2SAndroid Build Coastguard Worker 136*cc02d7e2SAndroid Build Coastguard Worker /** --- One-time event notification --- 137*cc02d7e2SAndroid Build Coastguard Worker 138*cc02d7e2SAndroid Build Coastguard Worker These operations act on a gpr_event, which should be initialized with 139*cc02d7e2SAndroid Build Coastguard Worker gpr_ev_init(), or with GPR_EVENT_INIT if static, e.g., 140*cc02d7e2SAndroid Build Coastguard Worker static gpr_event event_var = GPR_EVENT_INIT; 141*cc02d7e2SAndroid Build Coastguard Worker It requires no destruction. */ 142*cc02d7e2SAndroid Build Coastguard Worker 143*cc02d7e2SAndroid Build Coastguard Worker /** Initialize *ev. */ 144*cc02d7e2SAndroid Build Coastguard Worker GPRAPI void gpr_event_init(gpr_event* ev); 145*cc02d7e2SAndroid Build Coastguard Worker 146*cc02d7e2SAndroid Build Coastguard Worker /** Set *ev so that gpr_event_get() and gpr_event_wait() will return value. 147*cc02d7e2SAndroid Build Coastguard Worker Requires: *ev initialized; value != NULL; no prior or concurrent calls to 148*cc02d7e2SAndroid Build Coastguard Worker gpr_event_set(ev, ...) since initialization. */ 149*cc02d7e2SAndroid Build Coastguard Worker GPRAPI void gpr_event_set(gpr_event* ev, void* value); 150*cc02d7e2SAndroid Build Coastguard Worker 151*cc02d7e2SAndroid Build Coastguard Worker /** Return the value set by gpr_event_set(ev, ...), or NULL if no such call has 152*cc02d7e2SAndroid Build Coastguard Worker completed. If the result is non-NULL, all operations that occurred prior to 153*cc02d7e2SAndroid Build Coastguard Worker the gpr_event_set(ev, ...) set will be visible after this call returns. 154*cc02d7e2SAndroid Build Coastguard Worker Requires: *ev initialized. This operation is faster than acquiring a mutex 155*cc02d7e2SAndroid Build Coastguard Worker on most platforms. */ 156*cc02d7e2SAndroid Build Coastguard Worker GPRAPI void* gpr_event_get(gpr_event* ev); 157*cc02d7e2SAndroid Build Coastguard Worker 158*cc02d7e2SAndroid Build Coastguard Worker /** Wait until *ev is set by gpr_event_set(ev, ...), or abs_deadline is 159*cc02d7e2SAndroid Build Coastguard Worker exceeded, then return gpr_event_get(ev). Requires: *ev initialized. Use 160*cc02d7e2SAndroid Build Coastguard Worker abs_deadline==gpr_inf_future for no deadline. When the event has been 161*cc02d7e2SAndroid Build Coastguard Worker signalled before the call, this operation is faster than acquiring a mutex 162*cc02d7e2SAndroid Build Coastguard Worker on most platforms. */ 163*cc02d7e2SAndroid Build Coastguard Worker GPRAPI void* gpr_event_wait(gpr_event* ev, gpr_timespec abs_deadline); 164*cc02d7e2SAndroid Build Coastguard Worker 165*cc02d7e2SAndroid Build Coastguard Worker /** --- Reference counting --- 166*cc02d7e2SAndroid Build Coastguard Worker 167*cc02d7e2SAndroid Build Coastguard Worker These calls act on the type gpr_refcount. It requires no destruction. */ 168*cc02d7e2SAndroid Build Coastguard Worker 169*cc02d7e2SAndroid Build Coastguard Worker /** Initialize *r to value n. */ 170*cc02d7e2SAndroid Build Coastguard Worker GPRAPI void gpr_ref_init(gpr_refcount* r, int n); 171*cc02d7e2SAndroid Build Coastguard Worker 172*cc02d7e2SAndroid Build Coastguard Worker /** Increment the reference count *r. Requires *r initialized. */ 173*cc02d7e2SAndroid Build Coastguard Worker GPRAPI void gpr_ref(gpr_refcount* r); 174*cc02d7e2SAndroid Build Coastguard Worker 175*cc02d7e2SAndroid Build Coastguard Worker /** Increment the reference count *r. Requires *r initialized. 176*cc02d7e2SAndroid Build Coastguard Worker Crashes if refcount is zero */ 177*cc02d7e2SAndroid Build Coastguard Worker GPRAPI void gpr_ref_non_zero(gpr_refcount* r); 178*cc02d7e2SAndroid Build Coastguard Worker 179*cc02d7e2SAndroid Build Coastguard Worker /** Increment the reference count *r by n. Requires *r initialized, n > 0. */ 180*cc02d7e2SAndroid Build Coastguard Worker GPRAPI void gpr_refn(gpr_refcount* r, int n); 181*cc02d7e2SAndroid Build Coastguard Worker 182*cc02d7e2SAndroid Build Coastguard Worker /** Decrement the reference count *r and return non-zero iff it has reached 183*cc02d7e2SAndroid Build Coastguard Worker zero. . Requires *r initialized. */ 184*cc02d7e2SAndroid Build Coastguard Worker GPRAPI int gpr_unref(gpr_refcount* r); 185*cc02d7e2SAndroid Build Coastguard Worker 186*cc02d7e2SAndroid Build Coastguard Worker /** Return non-zero iff the reference count of *r is one, and thus is owned 187*cc02d7e2SAndroid Build Coastguard Worker by exactly one object. */ 188*cc02d7e2SAndroid Build Coastguard Worker GPRAPI int gpr_ref_is_unique(gpr_refcount* r); 189*cc02d7e2SAndroid Build Coastguard Worker 190*cc02d7e2SAndroid Build Coastguard Worker /** --- Stats counters --- 191*cc02d7e2SAndroid Build Coastguard Worker 192*cc02d7e2SAndroid Build Coastguard Worker These calls act on the integral type gpr_stats_counter. It requires no 193*cc02d7e2SAndroid Build Coastguard Worker destruction. Static instances may be initialized with 194*cc02d7e2SAndroid Build Coastguard Worker gpr_stats_counter c = GPR_STATS_INIT; 195*cc02d7e2SAndroid Build Coastguard Worker Beware: These operations do not imply memory barriers. Do not use them to 196*cc02d7e2SAndroid Build Coastguard Worker synchronize other events. */ 197*cc02d7e2SAndroid Build Coastguard Worker 198*cc02d7e2SAndroid Build Coastguard Worker /** Initialize *c to the value n. */ 199*cc02d7e2SAndroid Build Coastguard Worker GPRAPI void gpr_stats_init(gpr_stats_counter* c, intptr_t n); 200*cc02d7e2SAndroid Build Coastguard Worker 201*cc02d7e2SAndroid Build Coastguard Worker /** *c += inc. Requires: *c initialized. */ 202*cc02d7e2SAndroid Build Coastguard Worker GPRAPI void gpr_stats_inc(gpr_stats_counter* c, intptr_t inc); 203*cc02d7e2SAndroid Build Coastguard Worker 204*cc02d7e2SAndroid Build Coastguard Worker /** Return *c. Requires: *c initialized. */ 205*cc02d7e2SAndroid Build Coastguard Worker GPRAPI intptr_t gpr_stats_read(const gpr_stats_counter* c); 206*cc02d7e2SAndroid Build Coastguard Worker 207*cc02d7e2SAndroid Build Coastguard Worker /** ==================Example use of interface=================== 208*cc02d7e2SAndroid Build Coastguard Worker A producer-consumer queue of up to N integers, 209*cc02d7e2SAndroid Build Coastguard Worker illustrating the use of the calls in this interface. */ 210*cc02d7e2SAndroid Build Coastguard Worker #if 0 211*cc02d7e2SAndroid Build Coastguard Worker 212*cc02d7e2SAndroid Build Coastguard Worker #define N 4 213*cc02d7e2SAndroid Build Coastguard Worker 214*cc02d7e2SAndroid Build Coastguard Worker typedef struct queue { 215*cc02d7e2SAndroid Build Coastguard Worker gpr_cv non_empty; /* Signalled when length becomes non-zero. */ 216*cc02d7e2SAndroid Build Coastguard Worker gpr_cv non_full; /* Signalled when length becomes non-N. */ 217*cc02d7e2SAndroid Build Coastguard Worker gpr_mu mu; /* Protects all fields below. 218*cc02d7e2SAndroid Build Coastguard Worker (That is, except during initialization or 219*cc02d7e2SAndroid Build Coastguard Worker destruction, the fields below should be accessed 220*cc02d7e2SAndroid Build Coastguard Worker only by a thread that holds mu.) */ 221*cc02d7e2SAndroid Build Coastguard Worker int head; /* Index of head of queue 0..N-1. */ 222*cc02d7e2SAndroid Build Coastguard Worker int length; /* Number of valid elements in queue 0..N. */ 223*cc02d7e2SAndroid Build Coastguard Worker int elem[N]; /* elem[head .. head+length-1] are queue elements. */ 224*cc02d7e2SAndroid Build Coastguard Worker } queue; 225*cc02d7e2SAndroid Build Coastguard Worker 226*cc02d7e2SAndroid Build Coastguard Worker /* Initialize *q. */ 227*cc02d7e2SAndroid Build Coastguard Worker void queue_init(queue *q) { 228*cc02d7e2SAndroid Build Coastguard Worker gpr_mu_init(&q->mu); 229*cc02d7e2SAndroid Build Coastguard Worker gpr_cv_init(&q->non_empty); 230*cc02d7e2SAndroid Build Coastguard Worker gpr_cv_init(&q->non_full); 231*cc02d7e2SAndroid Build Coastguard Worker q->head = 0; 232*cc02d7e2SAndroid Build Coastguard Worker q->length = 0; 233*cc02d7e2SAndroid Build Coastguard Worker } 234*cc02d7e2SAndroid Build Coastguard Worker 235*cc02d7e2SAndroid Build Coastguard Worker /* Free storage associated with *q. */ 236*cc02d7e2SAndroid Build Coastguard Worker void queue_destroy(queue *q) { 237*cc02d7e2SAndroid Build Coastguard Worker gpr_mu_destroy(&q->mu); 238*cc02d7e2SAndroid Build Coastguard Worker gpr_cv_destroy(&q->non_empty); 239*cc02d7e2SAndroid Build Coastguard Worker gpr_cv_destroy(&q->non_full); 240*cc02d7e2SAndroid Build Coastguard Worker } 241*cc02d7e2SAndroid Build Coastguard Worker 242*cc02d7e2SAndroid Build Coastguard Worker /* Wait until there is room in *q, then append x to *q. */ 243*cc02d7e2SAndroid Build Coastguard Worker void queue_append(queue *q, int x) { 244*cc02d7e2SAndroid Build Coastguard Worker gpr_mu_lock(&q->mu); 245*cc02d7e2SAndroid Build Coastguard Worker /* To wait for a predicate without a deadline, loop on the negation of the 246*cc02d7e2SAndroid Build Coastguard Worker predicate, and use gpr_cv_wait(..., gpr_inf_future) inside the loop 247*cc02d7e2SAndroid Build Coastguard Worker to release the lock, wait, and reacquire on each iteration. Code that 248*cc02d7e2SAndroid Build Coastguard Worker makes the condition true should use gpr_cv_broadcast() on the 249*cc02d7e2SAndroid Build Coastguard Worker corresponding condition variable. The predicate must be on state 250*cc02d7e2SAndroid Build Coastguard Worker protected by the lock. */ 251*cc02d7e2SAndroid Build Coastguard Worker while (q->length == N) { 252*cc02d7e2SAndroid Build Coastguard Worker gpr_cv_wait(&q->non_full, &q->mu, gpr_inf_future); 253*cc02d7e2SAndroid Build Coastguard Worker } 254*cc02d7e2SAndroid Build Coastguard Worker if (q->length == 0) { /* Wake threads blocked in queue_remove(). */ 255*cc02d7e2SAndroid Build Coastguard Worker /* It's normal to use gpr_cv_broadcast() or gpr_signal() while 256*cc02d7e2SAndroid Build Coastguard Worker holding the lock. */ 257*cc02d7e2SAndroid Build Coastguard Worker gpr_cv_broadcast(&q->non_empty); 258*cc02d7e2SAndroid Build Coastguard Worker } 259*cc02d7e2SAndroid Build Coastguard Worker q->elem[(q->head + q->length) % N] = x; 260*cc02d7e2SAndroid Build Coastguard Worker q->length++; 261*cc02d7e2SAndroid Build Coastguard Worker gpr_mu_unlock(&q->mu); 262*cc02d7e2SAndroid Build Coastguard Worker } 263*cc02d7e2SAndroid Build Coastguard Worker 264*cc02d7e2SAndroid Build Coastguard Worker /* If it can be done without blocking, append x to *q and return non-zero. 265*cc02d7e2SAndroid Build Coastguard Worker Otherwise return 0. */ 266*cc02d7e2SAndroid Build Coastguard Worker int queue_try_append(queue *q, int x) { 267*cc02d7e2SAndroid Build Coastguard Worker int result = 0; 268*cc02d7e2SAndroid Build Coastguard Worker if (gpr_mu_trylock(&q->mu)) { 269*cc02d7e2SAndroid Build Coastguard Worker if (q->length != N) { 270*cc02d7e2SAndroid Build Coastguard Worker if (q->length == 0) { /* Wake threads blocked in queue_remove(). */ 271*cc02d7e2SAndroid Build Coastguard Worker gpr_cv_broadcast(&q->non_empty); 272*cc02d7e2SAndroid Build Coastguard Worker } 273*cc02d7e2SAndroid Build Coastguard Worker q->elem[(q->head + q->length) % N] = x; 274*cc02d7e2SAndroid Build Coastguard Worker q->length++; 275*cc02d7e2SAndroid Build Coastguard Worker result = 1; 276*cc02d7e2SAndroid Build Coastguard Worker } 277*cc02d7e2SAndroid Build Coastguard Worker gpr_mu_unlock(&q->mu); 278*cc02d7e2SAndroid Build Coastguard Worker } 279*cc02d7e2SAndroid Build Coastguard Worker return result; 280*cc02d7e2SAndroid Build Coastguard Worker } 281*cc02d7e2SAndroid Build Coastguard Worker 282*cc02d7e2SAndroid Build Coastguard Worker /* Wait until the *q is non-empty or deadline abs_deadline passes. If the 283*cc02d7e2SAndroid Build Coastguard Worker queue is non-empty, remove its head entry, place it in *head, and return 284*cc02d7e2SAndroid Build Coastguard Worker non-zero. Otherwise return 0. */ 285*cc02d7e2SAndroid Build Coastguard Worker int queue_remove(queue *q, int *head, gpr_timespec abs_deadline) { 286*cc02d7e2SAndroid Build Coastguard Worker int result = 0; 287*cc02d7e2SAndroid Build Coastguard Worker gpr_mu_lock(&q->mu); 288*cc02d7e2SAndroid Build Coastguard Worker /* To wait for a predicate with a deadline, loop on the negation of the 289*cc02d7e2SAndroid Build Coastguard Worker predicate or until gpr_cv_wait() returns true. Code that makes 290*cc02d7e2SAndroid Build Coastguard Worker the condition true should use gpr_cv_broadcast() on the corresponding 291*cc02d7e2SAndroid Build Coastguard Worker condition variable. The predicate must be on state protected by the 292*cc02d7e2SAndroid Build Coastguard Worker lock. */ 293*cc02d7e2SAndroid Build Coastguard Worker while (q->length == 0 && 294*cc02d7e2SAndroid Build Coastguard Worker !gpr_cv_wait(&q->non_empty, &q->mu, abs_deadline)) { 295*cc02d7e2SAndroid Build Coastguard Worker } 296*cc02d7e2SAndroid Build Coastguard Worker if (q->length != 0) { /* Queue is non-empty. */ 297*cc02d7e2SAndroid Build Coastguard Worker result = 1; 298*cc02d7e2SAndroid Build Coastguard Worker if (q->length == N) { /* Wake threads blocked in queue_append(). */ 299*cc02d7e2SAndroid Build Coastguard Worker gpr_cv_broadcast(&q->non_full); 300*cc02d7e2SAndroid Build Coastguard Worker } 301*cc02d7e2SAndroid Build Coastguard Worker *head = q->elem[q->head]; 302*cc02d7e2SAndroid Build Coastguard Worker q->head = (q->head + 1) % N; 303*cc02d7e2SAndroid Build Coastguard Worker q->length--; 304*cc02d7e2SAndroid Build Coastguard Worker } /* else deadline exceeded */ 305*cc02d7e2SAndroid Build Coastguard Worker gpr_mu_unlock(&q->mu); 306*cc02d7e2SAndroid Build Coastguard Worker return result; 307*cc02d7e2SAndroid Build Coastguard Worker } 308*cc02d7e2SAndroid Build Coastguard Worker #endif /* 0 */ 309*cc02d7e2SAndroid Build Coastguard Worker 310*cc02d7e2SAndroid Build Coastguard Worker #ifdef __cplusplus 311*cc02d7e2SAndroid Build Coastguard Worker } // extern "C" 312*cc02d7e2SAndroid Build Coastguard Worker #endif 313*cc02d7e2SAndroid Build Coastguard Worker 314*cc02d7e2SAndroid Build Coastguard Worker #endif /* GRPC_SUPPORT_SYNC_H */ 315