1275970Scy/* 2275970Scy * Copyright (c) 2008-2012 Niels Provos and Nick Mathewson 3275970Scy * 4275970Scy * Redistribution and use in source and binary forms, with or without 5275970Scy * modification, are permitted provided that the following conditions 6275970Scy * are met: 7275970Scy * 1. Redistributions of source code must retain the above copyright 8275970Scy * notice, this list of conditions and the following disclaimer. 9275970Scy * 2. Redistributions in binary form must reproduce the above copyright 10275970Scy * notice, this list of conditions and the following disclaimer in the 11275970Scy * documentation and/or other materials provided with the distribution. 12275970Scy * 3. The name of the author may not be used to endorse or promote products 13275970Scy * derived from this software without specific prior written permission. 14275970Scy * 15275970Scy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16275970Scy * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17275970Scy * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18275970Scy * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19275970Scy * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20275970Scy * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21275970Scy * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22275970Scy * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23275970Scy * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24275970Scy * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25275970Scy */ 26275970Scy#ifndef EVENT2_THREAD_H_INCLUDED_ 27275970Scy#define EVENT2_THREAD_H_INCLUDED_ 28275970Scy 29275970Scy/** @file event2/thread.h 30275970Scy 31275970Scy Functions for multi-threaded applications using Libevent. 32275970Scy 33275970Scy When using a multi-threaded application in which multiple threads 34275970Scy add and delete events from a single event base, Libevent needs to 35275970Scy lock its data structures. 36275970Scy 37275970Scy Like the memory-management function hooks, all of the threading functions 38275970Scy _must_ be set up before an event_base is created if you want the base to 39275970Scy use them. 40275970Scy 41275970Scy Most programs will either be using Windows threads or Posix threads. You 42275970Scy can configure Libevent to use one of these event_use_windows_threads() or 43275970Scy event_use_pthreads() respectively. If you're using another threading 44275970Scy library, you'll need to configure threading functions manually using 45275970Scy evthread_set_lock_callbacks() and evthread_set_condition_callbacks(). 46275970Scy 47275970Scy */ 48275970Scy 49275970Scy#include <event2/visibility.h> 50275970Scy 51275970Scy#ifdef __cplusplus 52275970Scyextern "C" { 53275970Scy#endif 54275970Scy 55275970Scy#include <event2/event-config.h> 56275970Scy 57275970Scy/** 58275970Scy @name Flags passed to lock functions 59275970Scy 60275970Scy @{ 61275970Scy*/ 62275970Scy/** A flag passed to a locking callback when the lock was allocated as a 63275970Scy * read-write lock, and we want to acquire or release the lock for writing. */ 64275970Scy#define EVTHREAD_WRITE 0x04 65275970Scy/** A flag passed to a locking callback when the lock was allocated as a 66275970Scy * read-write lock, and we want to acquire or release the lock for reading. */ 67275970Scy#define EVTHREAD_READ 0x08 68275970Scy/** A flag passed to a locking callback when we don't want to block waiting 69275970Scy * for the lock; if we can't get the lock immediately, we will instead 70275970Scy * return nonzero from the locking callback. */ 71275970Scy#define EVTHREAD_TRY 0x10 72275970Scy/**@}*/ 73275970Scy 74275970Scy#if !defined(EVENT__DISABLE_THREAD_SUPPORT) || defined(EVENT_IN_DOXYGEN_) 75275970Scy 76275970Scy#define EVTHREAD_LOCK_API_VERSION 1 77275970Scy 78275970Scy/** 79275970Scy @name Types of locks 80275970Scy 81275970Scy @{*/ 82275970Scy/** A recursive lock is one that can be acquired multiple times at once by the 83275970Scy * same thread. No other process can allocate the lock until the thread that 84275970Scy * has been holding it has unlocked it as many times as it locked it. */ 85275970Scy#define EVTHREAD_LOCKTYPE_RECURSIVE 1 86275970Scy/* A read-write lock is one that allows multiple simultaneous readers, but 87275970Scy * where any one writer excludes all other writers and readers. */ 88275970Scy#define EVTHREAD_LOCKTYPE_READWRITE 2 89275970Scy/**@}*/ 90275970Scy 91275970Scy/** This structure describes the interface a threading library uses for 92275970Scy * locking. It's used to tell evthread_set_lock_callbacks() how to use 93275970Scy * locking on this platform. 94275970Scy */ 95275970Scystruct evthread_lock_callbacks { 96275970Scy /** The current version of the locking API. Set this to 97275970Scy * EVTHREAD_LOCK_API_VERSION */ 98275970Scy int lock_api_version; 99275970Scy /** Which kinds of locks does this version of the locking API 100275970Scy * support? A bitfield of EVTHREAD_LOCKTYPE_RECURSIVE and 101275970Scy * EVTHREAD_LOCKTYPE_READWRITE. 102275970Scy * 103275970Scy * (Note that RECURSIVE locks are currently mandatory, and 104275970Scy * READWRITE locks are not currently used.) 105275970Scy **/ 106275970Scy unsigned supported_locktypes; 107275970Scy /** Function to allocate and initialize new lock of type 'locktype'. 108275970Scy * Returns NULL on failure. */ 109275970Scy void *(*alloc)(unsigned locktype); 110275970Scy /** Funtion to release all storage held in 'lock', which was created 111275970Scy * with type 'locktype'. */ 112275970Scy void (*free)(void *lock, unsigned locktype); 113275970Scy /** Acquire an already-allocated lock at 'lock' with mode 'mode'. 114275970Scy * Returns 0 on success, and nonzero on failure. */ 115275970Scy int (*lock)(unsigned mode, void *lock); 116275970Scy /** Release a lock at 'lock' using mode 'mode'. Returns 0 on success, 117275970Scy * and nonzero on failure. */ 118275970Scy int (*unlock)(unsigned mode, void *lock); 119275970Scy}; 120275970Scy 121275970Scy/** Sets a group of functions that Libevent should use for locking. 122275970Scy * For full information on the required callback API, see the 123275970Scy * documentation for the individual members of evthread_lock_callbacks. 124275970Scy * 125275970Scy * Note that if you're using Windows or the Pthreads threading library, you 126275970Scy * probably shouldn't call this function; instead, use 127275970Scy * evthread_use_windows_threads() or evthread_use_posix_threads() if you can. 128275970Scy */ 129275970ScyEVENT2_EXPORT_SYMBOL 130275970Scyint evthread_set_lock_callbacks(const struct evthread_lock_callbacks *); 131275970Scy 132275970Scy#define EVTHREAD_CONDITION_API_VERSION 1 133275970Scy 134275970Scystruct timeval; 135275970Scy 136275970Scy/** This structure describes the interface a threading library uses for 137275970Scy * condition variables. It's used to tell evthread_set_condition_callbacks 138275970Scy * how to use locking on this platform. 139275970Scy */ 140275970Scystruct evthread_condition_callbacks { 141275970Scy /** The current version of the conditions API. Set this to 142275970Scy * EVTHREAD_CONDITION_API_VERSION */ 143275970Scy int condition_api_version; 144275970Scy /** Function to allocate and initialize a new condition variable. 145275970Scy * Returns the condition variable on success, and NULL on failure. 146275970Scy * The 'condtype' argument will be 0 with this API version. 147275970Scy */ 148275970Scy void *(*alloc_condition)(unsigned condtype); 149275970Scy /** Function to free a condition variable. */ 150275970Scy void (*free_condition)(void *cond); 151275970Scy /** Function to signal a condition variable. If 'broadcast' is 1, all 152275970Scy * threads waiting on 'cond' should be woken; otherwise, only on one 153275970Scy * thread is worken. Should return 0 on success, -1 on failure. 154275970Scy * This function will only be called while holding the associated 155275970Scy * lock for the condition. 156275970Scy */ 157275970Scy int (*signal_condition)(void *cond, int broadcast); 158275970Scy /** Function to wait for a condition variable. The lock 'lock' 159275970Scy * will be held when this function is called; should be released 160275970Scy * while waiting for the condition to be come signalled, and 161275970Scy * should be held again when this function returns. 162275970Scy * If timeout is provided, it is interval of seconds to wait for 163275970Scy * the event to become signalled; if it is NULL, the function 164275970Scy * should wait indefinitely. 165275970Scy * 166275970Scy * The function should return -1 on error; 0 if the condition 167275970Scy * was signalled, or 1 on a timeout. */ 168275970Scy int (*wait_condition)(void *cond, void *lock, 169275970Scy const struct timeval *timeout); 170275970Scy}; 171275970Scy 172275970Scy/** Sets a group of functions that Libevent should use for condition variables. 173275970Scy * For full information on the required callback API, see the 174275970Scy * documentation for the individual members of evthread_condition_callbacks. 175275970Scy * 176275970Scy * Note that if you're using Windows or the Pthreads threading library, you 177275970Scy * probably shouldn't call this function; instead, use 178275970Scy * evthread_use_windows_threads() or evthread_use_pthreads() if you can. 179275970Scy */ 180275970ScyEVENT2_EXPORT_SYMBOL 181275970Scyint evthread_set_condition_callbacks( 182275970Scy const struct evthread_condition_callbacks *); 183275970Scy 184275970Scy/** 185275970Scy Sets the function for determining the thread id. 186275970Scy 187275970Scy @param base the event base for which to set the id function 188275970Scy @param id_fn the identify function Libevent should invoke to 189275970Scy determine the identity of a thread. 190275970Scy*/ 191275970ScyEVENT2_EXPORT_SYMBOL 192275970Scyvoid evthread_set_id_callback( 193275970Scy unsigned long (*id_fn)(void)); 194275970Scy 195275970Scy#if (defined(_WIN32) && !defined(EVENT__DISABLE_THREAD_SUPPORT)) || defined(EVENT_IN_DOXYGEN_) 196275970Scy/** Sets up Libevent for use with Windows builtin locking and thread ID 197275970Scy functions. Unavailable if Libevent is not built for Windows. 198275970Scy 199275970Scy @return 0 on success, -1 on failure. */ 200275970ScyEVENT2_EXPORT_SYMBOL 201275970Scyint evthread_use_windows_threads(void); 202275970Scy/** 203275970Scy Defined if Libevent was built with support for evthread_use_windows_threads() 204275970Scy*/ 205275970Scy#define EVTHREAD_USE_WINDOWS_THREADS_IMPLEMENTED 1 206275970Scy#endif 207275970Scy 208275970Scy#if defined(EVENT__HAVE_PTHREADS) || defined(EVENT_IN_DOXYGEN_) 209275970Scy/** Sets up Libevent for use with Pthreads locking and thread ID functions. 210275970Scy Unavailable if Libevent is not build for use with pthreads. Requires 211275970Scy libraries to link against Libevent_pthreads as well as Libevent. 212275970Scy 213275970Scy @return 0 on success, -1 on failure. */ 214275970ScyEVENT2_EXPORT_SYMBOL 215275970Scyint evthread_use_pthreads(void); 216275970Scy/** Defined if Libevent was built with support for evthread_use_pthreads() */ 217275970Scy#define EVTHREAD_USE_PTHREADS_IMPLEMENTED 1 218275970Scy 219275970Scy#endif 220275970Scy 221275970Scy/** Enable debugging wrappers around the current lock callbacks. If Libevent 222275970Scy * makes one of several common locking errors, exit with an assertion failure. 223275970Scy * 224275970Scy * If you're going to call this function, you must do so before any locks are 225275970Scy * allocated. 226275970Scy **/ 227275970ScyEVENT2_EXPORT_SYMBOL 228275970Scyvoid evthread_enable_lock_debugging(void); 229275970Scy 230275970Scy/* Old (misspelled) version: This is deprecated; use 231275970Scy * evthread_enable_log_debugging instead. */ 232275970ScyEVENT2_EXPORT_SYMBOL 233275970Scyvoid evthread_enable_lock_debuging(void); 234275970Scy 235275970Scy#endif /* EVENT__DISABLE_THREAD_SUPPORT */ 236275970Scy 237275970Scystruct event_base; 238275970Scy/** Make sure it's safe to tell an event base to wake up from another thread 239275970Scy or a signal handler. 240275970Scy 241275970Scy You shouldn't need to call this by hand; configuring the base with thread 242275970Scy support should be necessary and sufficient. 243275970Scy 244275970Scy @return 0 on success, -1 on failure. 245275970Scy */ 246275970ScyEVENT2_EXPORT_SYMBOL 247275970Scyint evthread_make_base_notifiable(struct event_base *base); 248275970Scy 249275970Scy#ifdef __cplusplus 250275970Scy} 251275970Scy#endif 252275970Scy 253275970Scy#endif /* EVENT2_THREAD_H_INCLUDED_ */ 254