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