1 module geario.net.channel.AbstractChannel; 2 3 import geario.event.selector.Selector; 4 import geario.net.channel.Types; 5 import geario.net.IoError; 6 import geario.logging; 7 import geario.util.worker; 8 9 import core.atomic; 10 import std.bitmanip; 11 import std.socket : socket_t; 12 13 14 /** 15 * 16 */ 17 abstract class AbstractChannel : Channel { 18 socket_t handle = socket_t.init; 19 ErrorEventHandler errorHandler; 20 21 Worker taskWorker = null; 22 23 protected bool _isRegistered = false; 24 private shared bool _isClosing = false; 25 protected shared bool _isClosed = false; 26 27 this(Selector loop, ChannelType type) { 28 this._loop = loop; 29 _type = type; 30 _flags = BitArray([false, false, false, false, false, false, false, 31 false, false, false, false, false, false, false, false, false]); 32 } 33 34 /** 35 * 36 */ 37 bool IsRegistered() { 38 return _isRegistered; 39 } 40 41 /** 42 * 43 */ 44 bool IsClosing() { 45 return _isClosing; 46 } 47 48 /** 49 * 50 */ 51 bool IsClosed() { 52 return _isClosed; 53 } 54 55 /** 56 * 57 */ 58 void Close() { 59 if (!_isClosed && cas(&_isClosing, false, true) ) { 60 version (GEAR_IO_DEBUG_MORE) 61 log.trace("channel[fd=%d] closing...", this.handle); 62 63 // closing 64 DoClose(); // close 65 _isClosed = true; 66 67 // closed 68 OnClose(); 69 _isClosing = false; 70 version (GEAR_IO_DEBUG) 71 log.trace("channel[fd=%d] closed", this.handle); 72 73 } else { 74 version (GEAR_IO_DEBUG) { 75 log.warn("The channel[fd=%d] has already been closed (%s) or closing (%s)", 76 this.handle, _isClosed, _isClosing); 77 } 78 } 79 } 80 81 protected void DoClose() { 82 83 } 84 85 void OnClose() { 86 version (GEAR_IO_DEBUG) 87 log.trace("onClose [fd=%d]...", this.handle); 88 _isRegistered = false; 89 _loop.Deregister(this); 90 Clear(); 91 92 version (GEAR_IO_DEBUG_MORE) 93 log.trace("onClose done [fd=%d]...", this.handle); 94 95 _isClosed = true; 96 } 97 98 protected void ErrorOccurred(ErrorCode code, string msg) { 99 debug log.warn("isRegistered: %s, isClosed: %s, msg=%s", _isRegistered, _isClosed, msg); 100 if (errorHandler !is null) { 101 errorHandler(new IoError(code, msg)); 102 } 103 } 104 105 void OnRead() { 106 assert(false, "not implemented"); 107 } 108 109 void OnWrite() { 110 assert(false, "not implemented"); 111 } 112 113 final bool HasFlag(ChannelFlag index) { 114 return _flags[index]; 115 } 116 117 @property ChannelType Type() { 118 return _type; 119 } 120 121 @property Selector eventLoop() { 122 return _loop; 123 } 124 125 void SetNext(AbstractChannel next) { 126 if (next is this) 127 return; // Can't set to self 128 next._next = _next; 129 next._priv = this; 130 if (_next) 131 _next._priv = next; 132 this._next = next; 133 } 134 135 void Clear() { 136 if (_priv) 137 _priv._next = _next; 138 if (_next) 139 _next._priv = _priv; 140 _next = null; 141 _priv = null; 142 } 143 144 mixin OverrideErro; 145 146 protected: 147 final void setFlag(ChannelFlag index, bool enable) { 148 _flags[index] = enable; 149 } 150 151 Selector _loop; 152 153 private: 154 BitArray _flags; 155 ChannelType _type; 156 157 AbstractChannel _priv; 158 AbstractChannel _next; 159 } 160 161 162 163 /** 164 https://stackoverflow.com/questions/40361869/how-to-wake-up-epoll-wait-before-any-event-happened 165 */ 166 class EventChannel : AbstractChannel { 167 this(Selector loop) { 168 super(loop, ChannelType.Event); 169 } 170 171 abstract void trigger(); 172 // override void Close() { 173 // if(_isClosing) 174 // return; 175 // _isClosing = true; 176 // version (GEAR_DEBUG) log.trace("closing [fd=%d]...", this.handle); 177 178 // if(isBusy) { 179 // import std.parallelism; 180 // version (GEAR_DEBUG) log.warn("Close operation delayed"); 181 // auto theTask = task(() { 182 // while(isBusy) { 183 // version (GEAR_DEBUG) log.info("waitting for idle [fd=%d]...", this.handle); 184 // // Thread.sleep(20.msecs); 185 // } 186 // super.Close(); 187 // }); 188 // taskPool.put(theTask); 189 // } else { 190 // super.Close(); 191 // } 192 // } 193 } 194 195 mixin template OverrideErro() { 196 bool IsError() { 197 return _error; 198 } 199 200 deprecated("Using errorMessage instead.") 201 alias erroString = ErrorMessage; 202 203 string ErrorMessage() { 204 return _errorMessage; 205 } 206 207 void ClearError() { 208 _error = false; 209 _errorMessage = ""; 210 } 211 212 bool _error = false; 213 string _errorMessage; 214 }