bthread.h 13.2 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 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285

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

#ifndef BAIDU_BTHREAD_BTHREAD_H
#define BAIDU_BTHREAD_BTHREAD_H

#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

// Create bthread `fn(arg)' with attributes `attr' and put the identifier into
// `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*),
                                void* __restrict arg) __THROW;

// Create bthread `fn(arg)' with attributes `attr' and put the identifier into
// `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*),
                                    void* __restrict arg) __THROW;

// Ask the bthread `tid' to stop. Operations which would suspend the thread
// except bthread_join will not block, instead they return ESTOP.
// This is a cooperative stopping mechanism.
// Returns 0 on success, errno otherwise.
extern int bthread_stop(bthread_t tid) __THROW;

// Returns 1 iff bthread_stop() was called on the thread or the thread does
// not exist, 0 otherwise.
extern int bthread_stopped(bthread_t tid) __THROW;

// Returns identifier of caller if caller is a bthread, 0 otherwise(Id of a
// bthread is never zero)
extern bthread_t bthread_self(void) __THROW;

// Compare two bthread identifiers.
// Returns a non-zero value if t1 and t2 are equal, zero otherwise.
extern int bthread_equal(bthread_t t1, bthread_t t2) __THROW;

// 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
// if `bt' is already terminated. The exit status of the bthread shall be 
// stored in *bthread_return (if it's not NULL), however at present it's 
// always set to NULL. There's no "detachment" in bthreads, all bthreads are
// "detached" as default and still joinable.
// Returns 0 on success, errno otherwise.
extern int bthread_join(bthread_t bt, void** bthread_return) __THROW;

// Track and join many bthreads.
// Notice that all bthread_list* functions are NOT thread-safe.
extern int  bthread_list_init(bthread_list_t* list,
                              unsigned size, unsigned conflict_size) __THROW;
extern void bthread_list_destroy(bthread_list_t* list) __THROW;
extern int  bthread_list_add(bthread_list_t* list, bthread_t tid) __THROW;
extern int bthread_list_stop(bthread_list_t* list) __THROW;
extern int  bthread_list_join(bthread_list_t* list) __THROW;

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

// Initialize thread attribute `attr' with default attributes.
extern int bthread_attr_init(bthread_attr_t* attr) __THROW;

// Destroy thread attribute `attr'.
extern int bthread_attr_destroy(bthread_attr_t* attr) __THROW;

// 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.
extern int bthread_getattr(bthread_t bt, bthread_attr_t* attr) __THROW;

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

// Get number of worker pthreads
extern int bthread_getconcurrency(void) __THROW;

// 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.
extern int bthread_setconcurrency(int num) __THROW;

// 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.
extern int bthread_yield(void) __THROW;

// Suspend current thread for at least `microseconds'
extern int bthread_usleep(uint64_t microseconds) __THROW;

// ---------------------------------------------
// 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,
                              const bthread_mutexattr_t* __restrict mutex_attr) __THROW;

// Destroy `mutex'.
extern int bthread_mutex_destroy(bthread_mutex_t* mutex) __THROW;

// Try to lock `mutex'.
extern int bthread_mutex_trylock(bthread_mutex_t* mutex) __THROW;

// Wait until lock for `mutex' becomes available and lock it.
extern int bthread_mutex_lock(bthread_mutex_t* mutex) __THROW;

// Wait until lock becomes available and lock it or time exceeds `abstime'
extern int bthread_mutex_timedlock(bthread_mutex_t* __restrict mutex,
                                   const struct timespec* __restrict abstime) __THROW;

// Unlock `mutex'.
extern int bthread_mutex_unlock(bthread_mutex_t* mutex) __THROW;

// -----------------------------------------------
// 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,
                             const bthread_condattr_t* __restrict cond_attr) __THROW;

// Destroy condition variable `cond'.
extern int bthread_cond_destroy(bthread_cond_t* cond) __THROW;

// Wake up one thread waiting for condition variable `cond'.
extern int bthread_cond_signal(bthread_cond_t* cond) __THROW;

// Wake up all threads waiting for condition variables `cond'.
extern int bthread_cond_broadcast(bthread_cond_t* cond) __THROW;

// 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,
                             bthread_mutex_t* __restrict mutex) __THROW;

// 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,
    const struct timespec* __restrict abstime) __THROW;

// -------------------------------------------
// 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,
                               const bthread_rwlockattr_t* __restrict attr) __THROW;

// Destroy read-write lock `rwlock'.
extern int bthread_rwlock_destroy(bthread_rwlock_t* rwlock) __THROW;

// Acquire read lock for `rwlock'.
extern int bthread_rwlock_rdlock(bthread_rwlock_t* rwlock) __THROW;

// Try to acquire read lock for `rwlock'.
extern int bthread_rwlock_tryrdlock(bthread_rwlock_t* rwlock) __THROW;

// Try to acquire read lock for `rwlock' or return after specfied time.
extern int bthread_rwlock_timedrdlock(
    bthread_rwlock_t* __restrict rwlock,
    const struct timespec* __restrict abstime) __THROW;

// Acquire write lock for `rwlock'.
extern int bthread_rwlock_wrlock(bthread_rwlock_t* rwlock) __THROW;

// Try to acquire write lock for `rwlock'.
extern int bthread_rwlock_trywrlock(bthread_rwlock_t* rwlock) __THROW;

// Try to acquire write lock for `rwlock' or return after specfied time.
extern int bthread_rwlock_timedwrlock(
    bthread_rwlock_t* __restrict rwlock,
    const struct timespec* __restrict abstime) __THROW;

// Unlock `rwlock'.
extern int bthread_rwlock_unlock(bthread_rwlock_t* rwlock) __THROW;

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

// Initialize attribute object `attr' with default values.
extern int bthread_rwlockattr_init(bthread_rwlockattr_t* attr) __THROW;

// Destroy attribute object `attr'.
extern int bthread_rwlockattr_destroy(bthread_rwlockattr_t* attr) __THROW;

// Return current setting of reader/writer preference.
extern int bthread_rwlockattr_getkind_np(const bthread_rwlockattr_t* attr,
                                         int* pref) __THROW;

// Set reader/write preference.
extern int bthread_rwlockattr_setkind_np(bthread_rwlockattr_t* attr,
                                         int pref) __THROW;


// ----------------------------------------------------------------------
// 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,
                                unsigned count) __THROW;

extern int bthread_barrier_destroy(bthread_barrier_t* barrier) __THROW;

extern int bthread_barrier_wait(bthread_barrier_t* barrier) __THROW;

// ---------------------------------------------------------------------
// 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,
                              void (*destructor)(void* data)) __THROW;

// 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.
extern int bthread_key_delete(bthread_key_t key) __THROW;

// 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
286
// NOTE: If the thread is not created by brpc server and lifetime is
gejun's avatar
gejun committed
287 288 289
// 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
290
// but noticeable in shortly-lived threads. Threads in brpc server
gejun's avatar
gejun committed
291 292 293 294 295 296 297 298 299 300 301 302 303 304
// 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.
extern int bthread_setspecific(bthread_key_t key, void* data) __THROW;

// 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.
extern void* bthread_getspecific(bthread_key_t key) __THROW;

__END_DECLS

#endif  // BAIDU_BTHREAD_BTHREAD_H