bthread.h 13.9 KB
Newer Older
gejun's avatar
gejun committed
1
// bthread - A M:N threading library to make applications more concurrent.
gejun's avatar
gejun committed
2
// Copyright (c) 2012 Baidu, Inc.
gejun's avatar
gejun committed
3 4 5 6 7 8 9 10 11 12 13 14
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
gejun's avatar
gejun committed
15 16 17 18

// Author: Ge,Jun (gejun@baidu.com)
// Date: Tue Jul 10 17:40:58 CST 2012

gejun's avatar
gejun committed
19 20
#ifndef BTHREAD_BTHREAD_H
#define BTHREAD_BTHREAD_H
gejun's avatar
gejun committed
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35

#include <pthread.h>
#include <sys/socket.h>
#include "bthread/types.h"
#include "bthread/errno.h"

#if defined(__cplusplus)
#  include <iostream>
#  include "bthread/mutex.h"        // use bthread_mutex_t in the RAII way
#endif

#include "bthread/id.h"

__BEGIN_DECLS

36
// Create bthread `fn(args)' with attributes `attr' and put the identifier into
gejun's avatar
gejun committed
37 38 39 40 41 42
// `tid'. Switch to the new thread and schedule old thread to run. Use this
// function when the new thread is more urgent.
// Returns 0 on success, errno otherwise.
extern int bthread_start_urgent(bthread_t* __restrict tid,
                                const bthread_attr_t* __restrict attr,
                                void * (*fn)(void*),
gejun's avatar
gejun committed
43
                                void* __restrict args);
gejun's avatar
gejun committed
44

45
// Create bthread `fn(args)' with attributes `attr' and put the identifier into
gejun's avatar
gejun committed
46 47 48 49 50 51 52
// `tid'. This function behaves closer to pthread_create: after scheduling the
// new thread to run, it returns. In another word, the new thread may take
// longer time than bthread_start_urgent() to run.
// Return 0 on success, errno otherwise.
extern int bthread_start_background(bthread_t* __restrict tid,
                                    const bthread_attr_t* __restrict attr,
                                    void * (*fn)(void*),
gejun's avatar
gejun committed
53
                                    void* __restrict args);
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72

// Wake up operations blocking the thread. Different functions may behave
// differently:
//   bthread_usleep(): returns -1 and sets errno to ESTOP if bthread_stop()
//                     is called, or to EINTR otherwise.
//   butex_wait(): returns -1 and sets errno to EINTR
//   bthread_mutex_*lock: unaffected (still blocking)
//   bthread_cond_*wait: wakes up and returns 0.
//   bthread_*join: unaffected.
// Common usage of interruption is to make a thread to quit ASAP.
//    [Thread1]                  [Thread2]
//   set stopping flag
//   bthread_interrupt(Thread2)
//                               wake up
//                               see the flag and quit
//                               may block again if the flag is unchanged
// bthread_interrupt() guarantees that Thread2 is woken up reliably no matter
// how the 2 threads are interleaved.
// Returns 0 on success, errno otherwise.
gejun's avatar
gejun committed
73
extern int bthread_interrupt(bthread_t tid);
gejun's avatar
gejun committed
74

75 76 77 78 79
// Make bthread_stopped() on the bthread return true and interrupt the bthread.
// Note that current bthread_stop() solely sets the built-in "stop flag" and
// calls bthread_interrupt(), which is different from earlier versions of
// bthread, and replaceable by user-defined stop flags plus calls to
// bthread_interrupt().
gejun's avatar
gejun committed
80
// Returns 0 on success, errno otherwise.
gejun's avatar
gejun committed
81
extern int bthread_stop(bthread_t tid);
gejun's avatar
gejun committed
82

83 84
// Returns 1 iff bthread_stop(tid) was called or the thread does not exist,
// 0 otherwise.
gejun's avatar
gejun committed
85
extern int bthread_stopped(bthread_t tid);
gejun's avatar
gejun committed
86 87 88

// Returns identifier of caller if caller is a bthread, 0 otherwise(Id of a
// bthread is never zero)
gejun's avatar
gejun committed
89
extern bthread_t bthread_self(void);
gejun's avatar
gejun committed
90 91 92

// Compare two bthread identifiers.
// Returns a non-zero value if t1 and t2 are equal, zero otherwise.
gejun's avatar
gejun committed
93
extern int bthread_equal(bthread_t t1, bthread_t t2);
gejun's avatar
gejun committed
94 95 96 97 98 99

// Terminate calling bthread/pthread and make `retval' available to any
// successful join with the terminating thread. This function does not return.
extern void bthread_exit(void* retval) __attribute__((__noreturn__));

// Make calling thread wait for termination of bthread `bt'. Return immediately
100 101 102 103 104 105
// if `bt' is already terminated.
// Notes:
//  - All bthreads are "detached" but still joinable.
//  - *bthread_return is always set to null. If you need to return value
//    from a bthread, pass the value via the `args' created the bthread.
//  - bthread_join() is not affected by bthread_interrupt.
gejun's avatar
gejun committed
106
// Returns 0 on success, errno otherwise.
gejun's avatar
gejun committed
107
extern int bthread_join(bthread_t bt, void** bthread_return);
gejun's avatar
gejun committed
108 109 110 111

// Track and join many bthreads.
// Notice that all bthread_list* functions are NOT thread-safe.
extern int  bthread_list_init(bthread_list_t* list,
gejun's avatar
gejun committed
112 113 114 115 116
                              unsigned size, unsigned conflict_size);
extern void bthread_list_destroy(bthread_list_t* list);
extern int  bthread_list_add(bthread_list_t* list, bthread_t tid);
extern int bthread_list_stop(bthread_list_t* list);
extern int  bthread_list_join(bthread_list_t* list);
gejun's avatar
gejun committed
117 118 119 120 121 122

// ------------------------------------------
// Functions for handling attributes.
// ------------------------------------------

// Initialize thread attribute `attr' with default attributes.
gejun's avatar
gejun committed
123
extern int bthread_attr_init(bthread_attr_t* attr);
gejun's avatar
gejun committed
124 125

// Destroy thread attribute `attr'.
gejun's avatar
gejun committed
126
extern int bthread_attr_destroy(bthread_attr_t* attr);
gejun's avatar
gejun committed
127 128 129 130

// Initialize bthread attribute `attr' with attributes corresponding to the
// already running bthread `bt'.  It shall be called on unitialized `attr'
// and destroyed with bthread_attr_destroy when no longer needed.
gejun's avatar
gejun committed
131
extern int bthread_getattr(bthread_t bt, bthread_attr_t* attr);
gejun's avatar
gejun committed
132 133 134 135 136 137

// ---------------------------------------------
// Functions for scheduling control.
// ---------------------------------------------

// Get number of worker pthreads
gejun's avatar
gejun committed
138
extern int bthread_getconcurrency(void);
gejun's avatar
gejun committed
139 140 141 142 143

// Set number of worker pthreads to `num'. After a successful call,
// bthread_getconcurrency() shall return new set number, but workers may
// take some time to quit or create.
// NOTE: currently concurrency cannot be reduced after any bthread created.
gejun's avatar
gejun committed
144
extern int bthread_setconcurrency(int num);
gejun's avatar
gejun committed
145 146 147 148

// Yield processor to another bthread. 
// Notice that current implementation is not fair, which means that 
// even if bthread_yield() is called, suspended threads may still starve.
gejun's avatar
gejun committed
149
extern int bthread_yield(void);
gejun's avatar
gejun committed
150 151

// Suspend current thread for at least `microseconds'
152
// Interruptible by bthread_interrupt().
gejun's avatar
gejun committed
153
extern int bthread_usleep(uint64_t microseconds);
gejun's avatar
gejun committed
154 155 156 157 158 159 160 161 162 163

// ---------------------------------------------
// Functions for mutex handling.
// ---------------------------------------------

// Initialize `mutex' using attributes in `mutex_attr', or use the
// default values if later is NULL.
// NOTE: mutexattr is not used in current mutex implementation. User shall
//       always pass a NULL attribute.
extern int bthread_mutex_init(bthread_mutex_t* __restrict mutex,
gejun's avatar
gejun committed
164
                              const bthread_mutexattr_t* __restrict mutex_attr);
gejun's avatar
gejun committed
165 166

// Destroy `mutex'.
gejun's avatar
gejun committed
167
extern int bthread_mutex_destroy(bthread_mutex_t* mutex);
gejun's avatar
gejun committed
168 169

// Try to lock `mutex'.
gejun's avatar
gejun committed
170
extern int bthread_mutex_trylock(bthread_mutex_t* mutex);
gejun's avatar
gejun committed
171 172

// Wait until lock for `mutex' becomes available and lock it.
gejun's avatar
gejun committed
173
extern int bthread_mutex_lock(bthread_mutex_t* mutex);
gejun's avatar
gejun committed
174 175 176

// Wait until lock becomes available and lock it or time exceeds `abstime'
extern int bthread_mutex_timedlock(bthread_mutex_t* __restrict mutex,
gejun's avatar
gejun committed
177
                                   const struct timespec* __restrict abstime);
gejun's avatar
gejun committed
178 179

// Unlock `mutex'.
gejun's avatar
gejun committed
180
extern int bthread_mutex_unlock(bthread_mutex_t* mutex);
gejun's avatar
gejun committed
181 182 183 184 185 186 187 188 189 190

// -----------------------------------------------
// Functions for handling conditional variables.
// -----------------------------------------------

// Initialize condition variable `cond' using attributes `cond_attr', or use
// the default values if later is NULL.
// NOTE: cond_attr is not used in current condition implementation. User shall
//       always pass a NULL attribute.
extern int bthread_cond_init(bthread_cond_t* __restrict cond,
gejun's avatar
gejun committed
191
                             const bthread_condattr_t* __restrict cond_attr);
gejun's avatar
gejun committed
192 193

// Destroy condition variable `cond'.
gejun's avatar
gejun committed
194
extern int bthread_cond_destroy(bthread_cond_t* cond);
gejun's avatar
gejun committed
195 196

// Wake up one thread waiting for condition variable `cond'.
gejun's avatar
gejun committed
197
extern int bthread_cond_signal(bthread_cond_t* cond);
gejun's avatar
gejun committed
198 199

// Wake up all threads waiting for condition variables `cond'.
gejun's avatar
gejun committed
200
extern int bthread_cond_broadcast(bthread_cond_t* cond);
gejun's avatar
gejun committed
201 202 203 204

// Wait for condition variable `cond' to be signaled or broadcast.
// `mutex' is assumed to be locked before.
extern int bthread_cond_wait(bthread_cond_t* __restrict cond,
gejun's avatar
gejun committed
205
                             bthread_mutex_t* __restrict mutex);
gejun's avatar
gejun committed
206 207 208 209 210 211 212 213

// Wait for condition variable `cond' to be signaled or broadcast until
// `abstime'. `mutex' is assumed to be locked before.  `abstime' is an
// absolute time specification; zero is the beginning of the epoch
// (00:00:00 GMT, January 1, 1970).
extern int bthread_cond_timedwait(
    bthread_cond_t* __restrict cond,
    bthread_mutex_t* __restrict mutex,
gejun's avatar
gejun committed
214
    const struct timespec* __restrict abstime);
gejun's avatar
gejun committed
215 216 217 218 219 220 221 222

// -------------------------------------------
// Functions for handling read-write locks.
// -------------------------------------------

// Initialize read-write lock `rwlock' using attributes `attr', or use
// the default values if later is NULL.
extern int bthread_rwlock_init(bthread_rwlock_t* __restrict rwlock,
gejun's avatar
gejun committed
223
                               const bthread_rwlockattr_t* __restrict attr);
gejun's avatar
gejun committed
224 225

// Destroy read-write lock `rwlock'.
gejun's avatar
gejun committed
226
extern int bthread_rwlock_destroy(bthread_rwlock_t* rwlock);
gejun's avatar
gejun committed
227 228

// Acquire read lock for `rwlock'.
gejun's avatar
gejun committed
229
extern int bthread_rwlock_rdlock(bthread_rwlock_t* rwlock);
gejun's avatar
gejun committed
230 231

// Try to acquire read lock for `rwlock'.
gejun's avatar
gejun committed
232
extern int bthread_rwlock_tryrdlock(bthread_rwlock_t* rwlock);
gejun's avatar
gejun committed
233 234 235 236

// Try to acquire read lock for `rwlock' or return after specfied time.
extern int bthread_rwlock_timedrdlock(
    bthread_rwlock_t* __restrict rwlock,
gejun's avatar
gejun committed
237
    const struct timespec* __restrict abstime);
gejun's avatar
gejun committed
238 239

// Acquire write lock for `rwlock'.
gejun's avatar
gejun committed
240
extern int bthread_rwlock_wrlock(bthread_rwlock_t* rwlock);
gejun's avatar
gejun committed
241 242

// Try to acquire write lock for `rwlock'.
gejun's avatar
gejun committed
243
extern int bthread_rwlock_trywrlock(bthread_rwlock_t* rwlock);
gejun's avatar
gejun committed
244 245 246 247

// Try to acquire write lock for `rwlock' or return after specfied time.
extern int bthread_rwlock_timedwrlock(
    bthread_rwlock_t* __restrict rwlock,
gejun's avatar
gejun committed
248
    const struct timespec* __restrict abstime);
gejun's avatar
gejun committed
249 250

// Unlock `rwlock'.
gejun's avatar
gejun committed
251
extern int bthread_rwlock_unlock(bthread_rwlock_t* rwlock);
gejun's avatar
gejun committed
252 253 254 255 256 257

// ---------------------------------------------------
// Functions for handling read-write lock attributes.
// ---------------------------------------------------

// Initialize attribute object `attr' with default values.
gejun's avatar
gejun committed
258
extern int bthread_rwlockattr_init(bthread_rwlockattr_t* attr);
gejun's avatar
gejun committed
259 260

// Destroy attribute object `attr'.
gejun's avatar
gejun committed
261
extern int bthread_rwlockattr_destroy(bthread_rwlockattr_t* attr);
gejun's avatar
gejun committed
262 263 264

// Return current setting of reader/writer preference.
extern int bthread_rwlockattr_getkind_np(const bthread_rwlockattr_t* attr,
gejun's avatar
gejun committed
265
                                         int* pref);
gejun's avatar
gejun committed
266 267 268

// Set reader/write preference.
extern int bthread_rwlockattr_setkind_np(bthread_rwlockattr_t* attr,
gejun's avatar
gejun committed
269
                                         int pref);
gejun's avatar
gejun committed
270 271 272 273 274 275 276 277


// ----------------------------------------------------------------------
// Functions for handling barrier which is a new feature in 1003.1j-2000.
// ----------------------------------------------------------------------

extern int bthread_barrier_init(bthread_barrier_t* __restrict barrier,
                                const bthread_barrierattr_t* __restrict attr,
gejun's avatar
gejun committed
278
                                unsigned count);
gejun's avatar
gejun committed
279

gejun's avatar
gejun committed
280
extern int bthread_barrier_destroy(bthread_barrier_t* barrier);
gejun's avatar
gejun committed
281

gejun's avatar
gejun committed
282
extern int bthread_barrier_wait(bthread_barrier_t* barrier);
gejun's avatar
gejun committed
283 284 285 286 287 288 289 290 291 292 293 294 295 296

// ---------------------------------------------------------------------
// Functions for handling thread-specific data. 
// Notice that they can be used in pthread: get pthread-specific data in 
// pthreads and get bthread-specific data in bthreads.
// ---------------------------------------------------------------------

// Create a key value identifying a slot in a thread-specific data area.
// Each thread maintains a distinct thread-specific data area.
// `destructor', if non-NULL, is called with the value associated to that key
// when the key is destroyed. `destructor' is not called if the value
// associated is NULL when the key is destroyed.
// Returns 0 on success, error code otherwise.
extern int bthread_key_create(bthread_key_t* key,
gejun's avatar
gejun committed
297
                              void (*destructor)(void* data));
gejun's avatar
gejun committed
298 299 300 301 302 303 304

// Delete a key previously returned by bthread_key_create().
// It is the responsibility of the application to free the data related to
// the deleted key in any running thread. No destructor is invoked by
// this function. Any destructor that may have been associated with key
// will no longer be called upon thread exit.
// Returns 0 on success, error code otherwise.
gejun's avatar
gejun committed
305
extern int bthread_key_delete(bthread_key_t key);
gejun's avatar
gejun committed
306 307 308 309 310

// Store `data' in the thread-specific slot identified by `key'.
// bthread_setspecific() is callable from within destructor. If the application
// does so, destructors will be repeatedly called for at most
// PTHREAD_DESTRUCTOR_ITERATIONS times to clear the slots.
gejun's avatar
gejun committed
311
// NOTE: If the thread is not created by brpc server and lifetime is
gejun's avatar
gejun committed
312 313 314
// very short(doing a little thing and exit), avoid using bthread-local. The
// reason is that bthread-local always allocate keytable on first call to 
// bthread_setspecific, the overhead is negligible in long-lived threads,
gejun's avatar
gejun committed
315
// but noticeable in shortly-lived threads. Threads in brpc server
gejun's avatar
gejun committed
316 317 318 319
// are special since they reuse keytables from a bthread_keytable_pool_t
// in the server.
// Returns 0 on success, error code otherwise.
// If the key is invalid or deleted, return EINVAL.
gejun's avatar
gejun committed
320
extern int bthread_setspecific(bthread_key_t key, void* data);
gejun's avatar
gejun committed
321 322 323 324

// Return current value of the thread-specific slot identified by `key'.
// If bthread_setspecific() had not been called in the thread, return NULL.
// If the key is invalid or deleted, return NULL.
gejun's avatar
gejun committed
325
extern void* bthread_getspecific(bthread_key_t key);
gejun's avatar
gejun committed
326 327 328

__END_DECLS

gejun's avatar
gejun committed
329
#endif  // BTHREAD_BTHREAD_H