Merge remote-tracking branch 'origin/master' into for-steve
[sxemacs] / src / events / event-queue.h
1 /*
2   event-queue.h -- New Generation Event Queue
3   Copyright (C) 2006, 2007, 2008 Sebastian Freundt
4
5   Author:  Sebastian Freundt <hroptatyr@sxemacs.org>
6
7   * This file is part of SXEmacs.
8   *
9   * Redistribution and use in source and binary forms, with or without
10   * modification, are permitted provided that the following conditions
11   * are met:
12   *
13   * 1. Redistributions of source code must retain the above copyright
14   *    notice, this list of conditions and the following disclaimer.
15   *
16   * 2. Redistributions in binary form must reproduce the above copyright
17   *    notice, this list of conditions and the following disclaimer in the
18   *    documentation and/or other materials provided with the distribution.
19   *
20   * 3. Neither the name of the author nor the names of any contributors
21   *    may be used to endorse or promote products derived from this
22   *    software without specific prior written permission.
23   *
24   * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
25   * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27   * DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
31   * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32   * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
33   * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
34   * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35   */
36
37 /* Inspired by XEmacs' events.c written by Jamie Zawinski */
38
39 /* Synched up with: Not in FSF. */
40
41 #ifndef INCLUDED_event_queue_h_
42 #define INCLUDED_event_queue_h_
43
44 #include "semaphore.h"
45
46 #ifdef ALL_DEBUG_FLAGS
47 #undef EQUEUE_DEBUG_FLAG
48 #define EQUEUE_DEBUG_FLAG
49 #endif
50
51 #define __EQUEUE_DEBUG__(args...)       fprintf(stderr, "event-queue " args)
52 #ifndef EQUEUE_DEBUG_FLAG
53 #define EQUEUE_DEBUG(args...)
54 #else
55 #define EQUEUE_DEBUG(args...)           __EQUEUE_DEBUG__(args)
56 #endif
57 #define EQUEUE_CRITICAL(args...)        __EQUEUE_DEBUG__("CRITICAL: " args)
58 #define EQUEUE_DEBUG_WORKER(args...)    EQUEUE_DEBUG("[worker] " args)
59 #define EQUEUE_DEBUG_SCRATCH(args...)   EQUEUE_DEBUG("[scratch] " args)
60
61 typedef struct event_queue_s *event_queue_t;
62 typedef struct event_prique_s *event_prique_t;
63
64 /* a prominent instance */
65 extern event_queue_t asyneq;
66
67 \f
68 /* ordinary FIFO-queue */
69 struct event_queue_s {
70         struct lcrecord_header lheader;
71         struct sxe_semaphore_s queue_sem;
72         dllist_t queue;
73 };
74
75 /* priority queue, pronounced: prick :) */
76 struct event_prique_s {
77         struct lcrecord_header lheader;
78         struct sxe_semaphore_s prique_sem;
79         /* since ase's heap implementation is not global we use a void* here */
80         void *prique;
81 };
82
83 DECLARE_LRECORD(event_queue, struct event_queue_s);
84 #define eq_queue_sem(_x)        ((_x)->queue_sem)
85 #define eq_queue(_x)            ((_x)->queue)
86 #define XEVENT_QUEUE(x)         XRECORD(x, event_queue, struct event_queue_s)
87 #define XSETEVENT_QUEUE(x, p)   XSETRECORD(x, p, event_queue)
88 #define EVENT_QUEUE_P(x)        RECORDP(x, event_queue)
89
90 DECLARE_LRECORD(event_prique, struct event_prique_s);
91 #define eq_prique_sem(_x)       ((_x)->prique_sem)
92 #define eq_prique(_x)           ((_x)->prique)
93 #define XEVENT_PRIQUE(x)        XRECORD(x, event_prique, struct event_prique_s)
94 #define XSETEVENT_PRIQUE(x, p)  XSETRECORD(x, p, event_prique)
95 #define EVENT_PRIQUE_P(x)       RECORDP(x, event_prique)
96
97 \f
98 extern event_queue_t make_noseeum_event_queue(void);
99 extern event_queue_t make_event_queue(void);
100 extern void free_event_queue(event_queue_t);
101 extern event_prique_t make_event_prique(void);
102 extern void free_event_prique(event_prique_t);
103
104 extern_inline void eq_enqueue(event_queue_t, Lisp_Object);
105 extern_inline Lisp_Object eq_dequeue(event_queue_t);
106 extern_inline void eq_noseeum_enqueue(event_queue_t, void*);
107 extern_inline void *eq_noseeum_dequeue(event_queue_t);
108 extern void eq_enqueue_event_chain(event_queue_t, Lisp_Object);
109 extern_inline size_t eq_queue_size(event_queue_t);
110 extern_inline int eq_queue_empty_p(event_queue_t);
111 extern_inline void eq_queue_synch(event_queue_t);
112 extern_inline void eq_queue_trigger(event_queue_t);
113 extern_inline void eq_queue_trigger_all(event_queue_t);
114
115 /* special purpose */
116 extern_inline void eq_dequeue_pro(Lisp_Object*, event_queue_t);
117
118 \f
119 extern_inline void
120 eq_enqueue(event_queue_t eq, Lisp_Object ev)
121 {
122         dllist_append(eq_queue(eq), (void*)ev);
123         return;
124 }
125
126 extern_inline Lisp_Object
127 eq_dequeue(event_queue_t eq)
128 {
129         return (Lisp_Object)(Lisp_Object*)dllist_pop_car(eq_queue(eq));
130 }
131
132 extern_inline void
133 eq_dequeue_pro(Lisp_Object *result, event_queue_t eq)
134 {
135         dllist_pop_and_pro_car(result, eq_queue(eq));
136         return;
137 }
138
139 extern_inline void
140 eq_noseeum_enqueue(event_queue_t eq, void *ev)
141 {
142         dllist_append(eq_queue(eq), ev);
143         return;
144 }
145
146 extern_inline void*
147 eq_noseeum_dequeue(event_queue_t eq)
148 {
149         return (void*)dllist_pop_car(eq_queue(eq));
150 }
151
152 extern_inline size_t
153 eq_queue_size(event_queue_t eq)
154 {
155         return dllist_get_size(eq_queue(eq));
156 }
157
158 extern_inline int
159 eq_queue_empty_p(event_queue_t eq)
160 {
161         return eq_queue_size(eq) == 0;
162 }
163
164 #define RETURN_FROM_EQ_TRAVERSE(_eq, _retval)                   \
165         RETURN_FROM_DLLIST_TRAVERSE(eq_queue(_eq), _retval)
166 #define EQ_TRAVERSE(_eq, _var, args...)                         \
167         WITH_DLLIST_TRAVERSE(                                   \
168                 eq_queue(_eq),                                  \
169                 _var = (Lisp_Object)dllist_item;                \
170                 args;                                           \
171                 )
172
173 extern_inline void
174 eq_queue_synch(event_queue_t eq)
175 {
176         SXE_SEMAPH_SYNCH(&eq_queue_sem(eq));
177 }
178
179 extern_inline void
180 eq_queue_trigger(event_queue_t eq)
181 {
182         SXE_SEMAPH_TRIGGER(&eq_queue_sem(eq));
183 }
184
185 extern_inline void
186 eq_queue_trigger_all(event_queue_t eq)
187 {
188         SXE_SEMAPH_TRIGGER_ALL(&eq_queue_sem(eq));
189 }
190
191 #endif  /* INCLUDED_event_queue_h_ */