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 }