1 /*******************************************************************************
2 
3     Custom event which can be registered with the EpollSelectDispatcher.
4 
5     An instance of this class can be registered with an EpollSelectDispatcher,
6     and triggered at will, causing it to be selected in the select loop. When it
7     is selected, a user-specified callback (given in the class' constructor) is
8     invoked.
9 
10     Two versions of the class exist, one which counts the number of calls to
11     trigger() before the callback is invoked (and passes the count to the
12     callback), and one which does not keep a count.
13 
14     Usage example:
15 
16     ---
17 
18         import ocean.io.select.client.SelectEvent;
19         import ocean.io.select.EpollSelectDispatcher;
20 
21         // Event handler
22         void handler ( )
23         {
24             // Do something
25         }
26 
27         auto dispatcher = new EpollSelectDispatcher;
28         auto event = new SelectEvent(&handler);
29 
30         dispatcher.register(event);
31 
32         dispatcher.eventLoop();
33 
34         // At this point, any time event.trigger is called, the eventLoop will
35         // select the event and invoke its handler callback.
36 
37     ---
38 
39     Copyright:
40         Copyright (c) 2009-2016 dunnhumby Germany GmbH.
41         All rights reserved.
42 
43     License:
44         Boost Software License Version 1.0. See LICENSE_BOOST.txt for details.
45         Alternatively, this file may be distributed under the terms of the Tango
46         3-Clause BSD License (see LICENSE_BSD.txt for details).
47 
48 *******************************************************************************/
49 
50 module ocean.io.select.client.SelectEvent;
51 
52 
53 
54 
55 import ocean.core.Verify;
56 
57 import ocean.sys.EventFD;
58 
59 import ocean.io.select.client.model.ISelectClient;
60 
61 
62 
63 /*******************************************************************************
64 
65     CountingSelectEvent class -- counts and reports the number of times the
66     trigger() method was called preivous to the event being fired in epoll and
67     the class' handle() method being invoked.
68 
69 *******************************************************************************/
70 
71 public abstract class ISelectEvent : IAdvancedSelectClient
72 {
73     /***************************************************************************
74 
75         Event file descriptor.
76 
77     ***************************************************************************/
78 
79     private EventFD event_fd;
80 
81 
82     /***************************************************************************
83 
84         Constructor. Creates a custom event and hooks it up to the provided
85         event handler.
86 
87     ***************************************************************************/
88 
89     public this ( )
90     {
91         this.event_fd = new EventFD;
92     }
93 
94 
95     /***************************************************************************
96 
97         Returs:
98             the epoll events to register for.
99 
100     ***************************************************************************/
101 
102     override Event events ( )
103     {
104         return Event.EPOLLIN;
105     }
106 
107 
108     /***************************************************************************
109 
110         Required by ISelectable interface.
111 
112         Returns:
113             file descriptor used to manage custom event
114 
115     ***************************************************************************/
116 
117     public override Handle fileHandle ( )
118     {
119         return this.event_fd.fileHandle;
120     }
121 
122 
123     /***************************************************************************
124 
125         Called from the select dispatcher when the event fires. Calls the
126         abstract handle_() method.
127 
128         Params:
129             event = select event which fired, must be Read
130 
131         Returns:
132             forwards return value of the abstract handle_() method -- false
133             indicates that the event should be unregistered with the selector,
134             true indicates that it should remain registered and able to fire
135             again
136 
137     ***************************************************************************/
138 
139     public override bool handle ( Event event )
140     {
141         verify(event == event.EPOLLIN);
142 
143         auto n = this.event_fd.handle();
144         verify(n > 0);
145 
146         return this.handle_(n);
147     }
148 
149 
150     /***************************************************************************
151 
152         Called from handle() when the event fires.
153 
154         Params:
155             n = number of times the event was triggered since the last time
156                 handle() was called by the select dispatcher
157 
158         Returns:
159             false indicates that the event should be unregistered with the
160             selector, true indicates that it should remain registered and able
161             to fire again
162 
163     ***************************************************************************/
164 
165     protected abstract bool handle_ ( ulong n );
166 
167 
168     /***************************************************************************
169 
170         Triggers the event.
171 
172     ***************************************************************************/
173 
174     public void trigger ( )
175     {
176         this.event_fd.trigger();
177     }
178 }
179 
180 
181 
182 /*******************************************************************************
183 
184     SelectEvent class -- calls the user-provided callback (passed to the
185     constructor) when the event is fired from epoll. The trigger() method causes
186     the event to fire.
187 
188 *******************************************************************************/
189 
190 public class SelectEvent : ISelectEvent
191 {
192     /***************************************************************************
193 
194         Alias for event handler delegate. The return value indicates whether the
195         event should remain registered with the epoll selector, or be
196         unregistered after handling.
197 
198     ***************************************************************************/
199 
200     public alias bool delegate ( ) Handler;
201 
202 
203     /***************************************************************************
204 
205         Event handler delegate.
206 
207     ***************************************************************************/
208 
209     private Handler handler;
210 
211 
212     /***************************************************************************
213 
214         Constructor.
215 
216         Params:
217             handler = event handler
218 
219     ***************************************************************************/
220 
221     public this ( scope Handler handler )
222     {
223         this.handler = handler;
224 
225         super();
226     }
227 
228 
229     /***************************************************************************
230 
231         Called from handle() when the event fires.
232 
233         Params:
234             n = number of times the event was triggered since the last time
235                 handle() was called by the select dispatcher (ignored)
236 
237         Returns:
238             forwards return value of event handler -- false indicates that the
239             event should be unregistered with the selector, true indicates that
240             it should remain registered and able to fire again
241 
242     ***************************************************************************/
243 
244     protected override bool handle_ ( ulong n )
245     {
246         verify(this.handler !is null);
247         return this.handler();
248     }
249 }
250 
251 
252 
253 /*******************************************************************************
254 
255     CountingSelectEvent class -- calls the user-provided callback (passed to the
256     constructor) when the event is fired from epoll. The trigger() method causes
257     the event to fire. The number of calls to trigger() which occurred before
258     the event fires is counted and passed to the callback.
259 
260 *******************************************************************************/
261 
262 public class CountingSelectEvent : ISelectEvent
263 {
264     /***************************************************************************
265 
266         Alias for event handler delegate. The return value indicates whether the
267         event should remain registered with the epoll selector, or be
268         unregistered after handling.
269 
270         The ulong passed to the delegate is the number of times the event has
271         been triggered since the last time handle() was called from epoll.
272 
273     ***************************************************************************/
274 
275     public alias bool delegate ( ulong n ) Handler;
276 
277 
278     /***************************************************************************
279 
280         Event handler delegate.
281 
282     ***************************************************************************/
283 
284     private Handler handler;
285 
286 
287     /***************************************************************************
288 
289         Constructor.
290 
291         Params:
292             handler = event handler
293 
294     ***************************************************************************/
295 
296     public this ( scope Handler handler )
297     {
298         this.handler = handler;
299 
300         super();
301     }
302 
303 
304     /***************************************************************************
305 
306         Called from handle() when the event fires.
307 
308         Params:
309             n = number of times the event was triggered since the last time
310                 handle() was called by the select dispatcher
311 
312         Returns:
313             forwards return value of event handler -- false indicates that the
314             event should be unregistered with the selector, true indicates that
315             it should remain registered and able to fire again
316 
317     ***************************************************************************/
318 
319     protected override bool handle_ ( ulong n )
320     {
321         return this.handler(n);
322     }
323 }
324