1 /* 2 * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 3. The name of the author may not be used to endorse or promote products 13 * derived from this software without specific prior written permission. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 #ifndef _DEFER_INTERNAL_H_ 27 #define _DEFER_INTERNAL_H_ 28 29 #ifdef __cplusplus 30 extern "C" { 31 #endif 32 33 #include "event2/event-config.h" 34 #include <sys/queue.h> 35 36 struct deferred_cb; 37 38 typedef void (*deferred_cb_fn)(struct deferred_cb *, void *); 39 40 /** A deferred_cb is a callback that can be scheduled to run as part of 41 * an event_base's event_loop, rather than running immediately. */ 42 struct deferred_cb { 43 /** Links to the adjacent active (pending) deferred_cb objects. */ 44 TAILQ_ENTRY (deferred_cb) cb_next; 45 /** True iff this deferred_cb is pending in an event_base. */ 46 unsigned queued : 1; 47 /** The function to execute when the callback runs. */ 48 deferred_cb_fn cb; 49 /** The function's second argument. */ 50 void *arg; 51 }; 52 53 /** A deferred_cb_queue is a list of deferred_cb that we can add to and run. */ 54 struct deferred_cb_queue { 55 /** Lock used to protect the queue. */ 56 void *lock; 57 58 /** How many entries are in the queue? */ 59 int active_count; 60 61 /** Function called when adding to the queue from another thread. */ 62 void (*notify_fn)(struct deferred_cb_queue *, void *); 63 void *notify_arg; 64 65 /** Deferred callback management: a list of deferred callbacks to 66 * run active the active events. */ 67 TAILQ_HEAD (deferred_cb_list, deferred_cb) deferred_cb_list; 68 }; 69 70 /** 71 Initialize an empty, non-pending deferred_cb. 72 73 @param deferred The deferred_cb structure to initialize. 74 @param cb The function to run when the deferred_cb executes. 75 @param arg The function's second argument. 76 */ 77 void event_deferred_cb_init(struct deferred_cb *, deferred_cb_fn, void *); 78 /** 79 Cancel a deferred_cb if it is currently scheduled in an event_base. 80 */ 81 void event_deferred_cb_cancel(struct deferred_cb_queue *, struct deferred_cb *); 82 /** 83 Activate a deferred_cb if it is not currently scheduled in an event_base. 84 */ 85 void event_deferred_cb_schedule(struct deferred_cb_queue *, struct deferred_cb *); 86 87 #define LOCK_DEFERRED_QUEUE(q) \ 88 EVLOCK_LOCK((q)->lock, 0) 89 #define UNLOCK_DEFERRED_QUEUE(q) \ 90 EVLOCK_UNLOCK((q)->lock, 0) 91 92 #ifdef __cplusplus 93 } 94 #endif 95 96 void event_deferred_cb_queue_init(struct deferred_cb_queue *); 97 struct deferred_cb_queue *event_base_get_deferred_cb_queue(struct event_base *); 98 99 #endif /* _EVENT_INTERNAL_H_ */ 100 101