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