1 /******************************************************************************
2 
3     Base class for fiber based registrable client objects for the
4     SelectDispatcher
5 
6     Contains the five things that the fiber based SelectDispatcher needs:
7         1. the I/O device instance,
8         2. the I/O events to register the device for,
9         3. the event handler to invoke when an event occured for the device,
10         4. the finalizer that resumes the fiber,
11         5. the error handler that kills the fiber.
12 
13     Copyright:
14         Copyright (c) 2009-2016 dunnhumby Germany GmbH.
15         All rights reserved.
16 
17     License:
18         Boost Software License Version 1.0. See LICENSE_BOOST.txt for details.
19         Alternatively, this file may be distributed under the terms of the Tango
20         3-Clause BSD License (see LICENSE_BSD.txt for details).
21 
22  ******************************************************************************/
23 
24 module ocean.io.select.client.model.IFiberSelectClient;
25 
26 
27 import ocean.core.Verify;
28 
29 import ocean.io.select.client.model.ISelectClient;
30 
31 import ocean.io.select.fiber.SelectFiber;
32 
33 import ocean.io.select.EpollSelectDispatcher;
34 
35 import ocean.core.ExceptionDefinitions: IOException;
36 
37 
38 /******************************************************************************
39 
40     IFiberSelectClient abstract class
41 
42  ******************************************************************************/
43 
44 abstract class IFiberSelectClient : IAdvancedSelectClient
45 {
46     /**************************************************************************
47 
48         Type alias for subclass constructors
49 
50      **************************************************************************/
51 
52     public alias .SelectFiber SelectFiber;
53 
54     /**************************************************************************
55 
56         Fiber instance
57 
58         Note that the instance is not const, as it is occasionally useful to be
59         able to change the select client's fiber after construction. An example
60         of this use case would be when a select client instance is created for
61         use with a socket connection (i.e. fd, i.e. fiber), but then, some time
62         later, needs to be re-used for a different socket connection -
63         necessitating a fiber switch.
64 
65      **************************************************************************/
66 
67     public SelectFiber fiber;
68 
69     /**************************************************************************
70 
71         The fiber must always be non-null.
72 
73      **************************************************************************/
74 
75     invariant ( )
76     {
77         assert(this.fiber !is null, typeof(this).stringof ~ " fiber is null");
78     }
79 
80     /**************************************************************************
81 
82         Flag set to true when the error_() method is called due to an I/O error
83         event. The flag is always reset in the finalize() method.
84 
85      **************************************************************************/
86 
87     public bool io_error;
88 
89     /**************************************************************************
90 
91         Constructor
92 
93         Params:
94             fiber   = fiber to resume on finalize() or kill on error()
95 
96      **************************************************************************/
97 
98     protected this ( SelectFiber fiber )
99     {
100         this.fiber = fiber;
101     }
102 
103     /**************************************************************************
104 
105         Finalize method, called after this instance has been unregistered from
106         the Dispatcher; kills the fiber and calls the super-class' finalize()
107         method (which calls a finalizer delegate, if one has been set).
108 
109         The fiber must be waiting or finished as it is ought to be when in
110         Dispatcher context.
111 
112         Params:
113             status = status why this method is called
114 
115      **************************************************************************/
116 
117     public override void finalize ( FinalizeStatus status )
118     {
119         verify(!this.fiber.running);
120 
121         try
122         {
123             if (this.fiber.waiting)
124             {
125                 this.fiber.kill();
126             }
127 
128             this.fiber.clear();
129             super.finalize(status);
130         }
131         finally
132         {
133             this.io_error = false;
134         }
135     }
136 
137     /**************************************************************************
138 
139         Error reporting method, called when either an Exception is caught from
140         handle() or an error event is reported; kills the fiber.
141 
142         Params:
143             e = Exception thrown by handle()
144             event     = Selector event while exception was caught
145 
146      **************************************************************************/
147 
148     protected override void error_ ( Exception e, Event event )
149     {
150         this.io_error = cast(IOException)e !is null;
151 
152         if (this.fiber.waiting)
153         {
154             this.fiber.kill(__FILE__, __LINE__);
155         }
156 
157         super.error_(e, event);
158     }
159 
160 
161     /**************************************************************************
162 
163         Timeout method, called after this a timeout has occurred in the
164         SelectDispatcher; kills the fiber.
165 
166      **************************************************************************/
167 
168     override public void timeout ( )
169     {
170         if (this.fiber.waiting)
171         {
172             this.fiber.kill(__FILE__, __LINE__);
173         }
174 
175         super.timeout();
176     }
177 }
178