123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253 |
- /*
- * Copyright (c) 2008-2012 Niels Provos and Nick Mathewson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #ifndef EVENT2_THREAD_H_INCLUDED_
- #define EVENT2_THREAD_H_INCLUDED_
- /** @file event2/thread.h
- Functions for multi-threaded applications using Libevent.
- When using a multi-threaded application in which multiple threads
- add and delete events from a single event base, Libevent needs to
- lock its data structures.
- Like the memory-management function hooks, all of the threading functions
- _must_ be set up before an event_base is created if you want the base to
- use them.
- Most programs will either be using Windows threads or Posix threads. You
- can configure Libevent to use one of these event_use_windows_threads() or
- event_use_pthreads() respectively. If you're using another threading
- library, you'll need to configure threading functions manually using
- evthread_set_lock_callbacks() and evthread_set_condition_callbacks().
- */
- #include <event2/visibility.h>
- #ifdef __cplusplus
- extern "C" {
- #endif
- #include <event2/event-config.h>
- /**
- @name Flags passed to lock functions
- @{
- */
- /** A flag passed to a locking callback when the lock was allocated as a
- * read-write lock, and we want to acquire or release the lock for writing. */
- #define EVTHREAD_WRITE 0x04
- /** A flag passed to a locking callback when the lock was allocated as a
- * read-write lock, and we want to acquire or release the lock for reading. */
- #define EVTHREAD_READ 0x08
- /** A flag passed to a locking callback when we don't want to block waiting
- * for the lock; if we can't get the lock immediately, we will instead
- * return nonzero from the locking callback. */
- #define EVTHREAD_TRY 0x10
- /**@}*/
- #if !defined(EVENT__DISABLE_THREAD_SUPPORT) || defined(EVENT_IN_DOXYGEN_)
- #define EVTHREAD_LOCK_API_VERSION 1
- /**
- @name Types of locks
- @{*/
- /** A recursive lock is one that can be acquired multiple times at once by the
- * same thread. No other process can allocate the lock until the thread that
- * has been holding it has unlocked it as many times as it locked it. */
- #define EVTHREAD_LOCKTYPE_RECURSIVE 1
- /* A read-write lock is one that allows multiple simultaneous readers, but
- * where any one writer excludes all other writers and readers. */
- #define EVTHREAD_LOCKTYPE_READWRITE 2
- /**@}*/
- /** This structure describes the interface a threading library uses for
- * locking. It's used to tell evthread_set_lock_callbacks() how to use
- * locking on this platform.
- */
- struct evthread_lock_callbacks {
- /** The current version of the locking API. Set this to
- * EVTHREAD_LOCK_API_VERSION */
- int lock_api_version;
- /** Which kinds of locks does this version of the locking API
- * support? A bitfield of EVTHREAD_LOCKTYPE_RECURSIVE and
- * EVTHREAD_LOCKTYPE_READWRITE.
- *
- * (Note that RECURSIVE locks are currently mandatory, and
- * READWRITE locks are not currently used.)
- **/
- unsigned supported_locktypes;
- /** Function to allocate and initialize new lock of type 'locktype'.
- * Returns NULL on failure. */
- void *(*alloc)(unsigned locktype);
- /** Funtion to release all storage held in 'lock', which was created
- * with type 'locktype'. */
- void (*free)(void *lock, unsigned locktype);
- /** Acquire an already-allocated lock at 'lock' with mode 'mode'.
- * Returns 0 on success, and nonzero on failure. */
- int (*lock)(unsigned mode, void *lock);
- /** Release a lock at 'lock' using mode 'mode'. Returns 0 on success,
- * and nonzero on failure. */
- int (*unlock)(unsigned mode, void *lock);
- };
- /** Sets a group of functions that Libevent should use for locking.
- * For full information on the required callback API, see the
- * documentation for the individual members of evthread_lock_callbacks.
- *
- * Note that if you're using Windows or the Pthreads threading library, you
- * probably shouldn't call this function; instead, use
- * evthread_use_windows_threads() or evthread_use_posix_threads() if you can.
- */
- EVENT2_EXPORT_SYMBOL
- int evthread_set_lock_callbacks(const struct evthread_lock_callbacks *);
- #define EVTHREAD_CONDITION_API_VERSION 1
- struct timeval;
- /** This structure describes the interface a threading library uses for
- * condition variables. It's used to tell evthread_set_condition_callbacks
- * how to use locking on this platform.
- */
- struct evthread_condition_callbacks {
- /** The current version of the conditions API. Set this to
- * EVTHREAD_CONDITION_API_VERSION */
- int condition_api_version;
- /** Function to allocate and initialize a new condition variable.
- * Returns the condition variable on success, and NULL on failure.
- * The 'condtype' argument will be 0 with this API version.
- */
- void *(*alloc_condition)(unsigned condtype);
- /** Function to free a condition variable. */
- void (*free_condition)(void *cond);
- /** Function to signal a condition variable. If 'broadcast' is 1, all
- * threads waiting on 'cond' should be woken; otherwise, only on one
- * thread is worken. Should return 0 on success, -1 on failure.
- * This function will only be called while holding the associated
- * lock for the condition.
- */
- int (*signal_condition)(void *cond, int broadcast);
- /** Function to wait for a condition variable. The lock 'lock'
- * will be held when this function is called; should be released
- * while waiting for the condition to be come signalled, and
- * should be held again when this function returns.
- * If timeout is provided, it is interval of seconds to wait for
- * the event to become signalled; if it is NULL, the function
- * should wait indefinitely.
- *
- * The function should return -1 on error; 0 if the condition
- * was signalled, or 1 on a timeout. */
- int (*wait_condition)(void *cond, void *lock,
- const struct timeval *timeout);
- };
- /** Sets a group of functions that Libevent should use for condition variables.
- * For full information on the required callback API, see the
- * documentation for the individual members of evthread_condition_callbacks.
- *
- * Note that if you're using Windows or the Pthreads threading library, you
- * probably shouldn't call this function; instead, use
- * evthread_use_windows_threads() or evthread_use_pthreads() if you can.
- */
- EVENT2_EXPORT_SYMBOL
- int evthread_set_condition_callbacks(
- const struct evthread_condition_callbacks *);
- /**
- Sets the function for determining the thread id.
- @param base the event base for which to set the id function
- @param id_fn the identify function Libevent should invoke to
- determine the identity of a thread.
- */
- EVENT2_EXPORT_SYMBOL
- void evthread_set_id_callback(
- unsigned long (*id_fn)(void));
- #if (defined(_WIN32) && !defined(EVENT__DISABLE_THREAD_SUPPORT)) || defined(EVENT_IN_DOXYGEN_)
- /** Sets up Libevent for use with Windows builtin locking and thread ID
- functions. Unavailable if Libevent is not built for Windows.
- @return 0 on success, -1 on failure. */
- EVENT2_EXPORT_SYMBOL
- int evthread_use_windows_threads(void);
- /**
- Defined if Libevent was built with support for evthread_use_windows_threads()
- */
- #define EVTHREAD_USE_WINDOWS_THREADS_IMPLEMENTED 1
- #endif
- #if defined(EVENT__HAVE_PTHREADS) || defined(EVENT_IN_DOXYGEN_)
- /** Sets up Libevent for use with Pthreads locking and thread ID functions.
- Unavailable if Libevent is not build for use with pthreads. Requires
- libraries to link against Libevent_pthreads as well as Libevent.
- @return 0 on success, -1 on failure. */
- EVENT2_EXPORT_SYMBOL
- int evthread_use_pthreads(void);
- /** Defined if Libevent was built with support for evthread_use_pthreads() */
- #define EVTHREAD_USE_PTHREADS_IMPLEMENTED 1
- #endif
- /** Enable debugging wrappers around the current lock callbacks. If Libevent
- * makes one of several common locking errors, exit with an assertion failure.
- *
- * If you're going to call this function, you must do so before any locks are
- * allocated.
- **/
- EVENT2_EXPORT_SYMBOL
- void evthread_enable_lock_debugging(void);
- /* Old (misspelled) version: This is deprecated; use
- * evthread_enable_log_debugging instead. */
- EVENT2_EXPORT_SYMBOL
- void evthread_enable_lock_debuging(void);
- #endif /* EVENT__DISABLE_THREAD_SUPPORT */
- struct event_base;
- /** Make sure it's safe to tell an event base to wake up from another thread
- or a signal handler.
- You shouldn't need to call this by hand; configuring the base with thread
- support should be necessary and sufficient.
- @return 0 on success, -1 on failure.
- */
- EVENT2_EXPORT_SYMBOL
- int evthread_make_base_notifiable(struct event_base *base);
- #ifdef __cplusplus
- }
- #endif
- #endif /* EVENT2_THREAD_H_INCLUDED_ */
|