1 /*******************************************************************************
2 
3     Custom event for use with fibers and epoll, allowing a process to be
4     suspended until the event is triggered.
5 
6     Usage example:
7 
8     ---
9 
10         import ocean.io.select.client.FiberSelectEvent;
11         import ocean.io.select.EpollSelectDispatcher;
12 
13         auto fiber = new MessageFiber(&coroutine);
14 
15         auto epoll = new EpollSelectDispatcher;
16         auto event = new FiberSelectEvent(fiber, epoll);
17 
18         // Fiber method
19         void coroutine ( )
20         {
21             // Do something.
22 
23             // Wait on the event, suspends the fiber.
24             event.wait();
25 
26             // When event.trigger is called (from elsewhere), the fiber is
27             // resumed.
28         }
29 
30     ---
31 
32     Copyright:
33         Copyright (c) 2009-2016 dunnhumby Germany GmbH.
34         All rights reserved.
35 
36     License:
37         Boost Software License Version 1.0. See LICENSE_BOOST.txt for details.
38         Alternatively, this file may be distributed under the terms of the Tango
39         3-Clause BSD License (see LICENSE_BSD.txt for details).
40 
41 *******************************************************************************/
42 
43 module ocean.io.select.client.FiberSelectEvent;
44 
45 
46 import ocean.core.MessageFiber;
47 
48 import ocean.core.Verify;
49 
50 import ocean.sys.EventFD;
51 
52 import ocean.io.select.client.model.IFiberSelectClient;
53 
54 
55 /*******************************************************************************
56 
57     Fiber select event class
58 
59 *******************************************************************************/
60 
61 public class FiberSelectEvent : IFiberSelectClient
62 {
63     /***************************************************************************
64 
65         Token used when suspending / resuming fiber.
66 
67     ***************************************************************************/
68 
69     static private MessageFiber.Token EventFired;
70 
71 
72     /***************************************************************************
73 
74         Static ctor. Initialises fiber token.
75 
76     ***************************************************************************/
77 
78     static this ( )
79     {
80         EventFired = MessageFiber.Token("event_fired");
81     }
82 
83 
84     /***************************************************************************
85 
86         Custom event.
87 
88     ***************************************************************************/
89 
90     private EventFD event;
91 
92 
93     /***************************************************************************
94 
95         Constructor.
96 
97         Params:
98             fiber = fiber to suspend / resume with event wait / trigger
99 
100     ***************************************************************************/
101 
102     public this ( SelectFiber fiber )
103     {
104         super(fiber);
105 
106         this.event = new EventFD;
107     }
108 
109     /***************************************************************************
110 
111         Returs:
112             the epoll events to register for.
113 
114     ***************************************************************************/
115 
116     public override Event events ( )
117     {
118         return Event.EPOLLIN;
119     }
120 
121     /***************************************************************************
122 
123         Required by ISelectable interface.
124 
125         Returns:
126             file descriptor used to manage custom event
127 
128     ***************************************************************************/
129 
130     public override Handle fileHandle ( )
131     {
132         return this.event.fileHandle;
133     }
134 
135 
136     /***************************************************************************
137 
138         Triggers the event.
139 
140     ***************************************************************************/
141 
142     public void trigger ( )
143     {
144         this.event.trigger();
145     }
146 
147 
148     /***************************************************************************
149 
150         Suspends the fiber until the event is triggered.
151 
152     ***************************************************************************/
153 
154     public void wait ( )
155     {
156         super.fiber.register(this);
157         super.fiber.suspend(EventFired, this, fiber.Message(true));
158     }
159 
160 
161     /***************************************************************************
162 
163         Combining trigger() then wait(), this method causes the epoll event loop
164         to be resumed, giving other select clients a chance to do something.
165 
166     ***************************************************************************/
167 
168     public void cede ( )
169     {
170         this.trigger;
171         this.wait;
172     }
173 
174 
175     /***************************************************************************
176 
177         Handles events which occurred for the custom event fd.
178 
179         (Implements an abstract super class method.)
180 
181         Returns:
182             false if the fiber is finished or true if it keeps going
183 
184     ***************************************************************************/
185 
186     public override bool handle ( Event events )
187     {
188         verify(super.fiber.waiting);
189 
190         this.event.handle();
191 
192         SelectFiber.Message message = super.fiber.resume(EventFired, this);
193 
194         return (message.active == message.active.num)? message.num != 0 : false;
195     }
196 }
197