Forum Navigation
EpollSelector broken?
Posted: 03/23/09 15:24:22 Modified: 03/23/09 15:27:40I grabbed the latest trunk (4435) and used it with a current project I'm working on.
In this project I used the EPollSelector.reregister() function. After updating tango, I
changed all occurrences of the EPollSelector.reregister() function to EPollSelector.register(),
but unfortunately it doesn't work.After digging in a bit I noticed that the SelectionKey? class has been changed to a struct.
After changing it back to a class with a constructor, I was able to modify EPollSelector
to use a pointer to change the key event if it is found in _keys, just as it was like in
the old reregister function.I was now wondering why the SelectionKey? class has been changed to a struct.
Here is the patch for EPollSelector:
Index: EpollSelector.d =================================================================== --- EpollSelector.d (revision 4435) +++ EpollSelector.d (working copy) @@ -224,17 +224,17 @@ } body { - auto key = conduit.fileHandle() in _keys; + SelectionKey* key = (conduit.fileHandle() in _keys); if (key !is null) { epoll_event event; - key.events = events; - key.attachment = attachment; + (*key).events = events; + (*key).attachment = attachment; event.events = events; - event.data.ptr = cast(void*) key; + event.data.ptr = cast(void*) *key; if (epoll_ctl(_epfd, EPOLL_CTL_MOD, conduit.fileHandle(), &event) != 0) { @@ -244,7 +244,7 @@ else { epoll_event event; - SelectionKey newkey = SelectionKey(conduit, events, attachment); + SelectionKey newkey = new SelectionKey(conduit, events, attachment); event.events = events;
Here is a sample program, which i used to test the change. It doesnt work with the latest trunk, but works when SelectionKey? is modified to be a class and the modified EPollSelector as above:
module epoll; private import tango.io.selector.EpollSelector; private import tango.io.Stdout; private import tango.net.Socket, tango.net.ServerSocket, tango.net.SocketConduit, tango.net.http.HttpConst; /** * infinite wait for EPoll */ private const int EPOLLWAIT_INFINITE = -1; void main(char[][] args) { SocketConduit _conduit; SocketConduit[int] _connections; EpollSelector _selector; int _event_count; int _conduit_filehandle; ServerSocket socket = new ServerSocket(new InternetAddress(8000),400,true); /** * initialize EpollSelector */ _selector = new EpollSelector(); _selector.open(1, 1); _selector.register(socket, Event.Read); /** * set Server Socket to non blocking */ socket.socket.blocking(false); char[16] buffer; while(true) { try { _event_count = _selector.select(EPOLLWAIT_INFINITE); } catch (Exception e) {} if ( _event_count > 0 ) { foreach (SelectionKey key; _selector.selectedSet()) { try { Stdout.formatln("try to get conduit."); _conduit = (cast(ServerSocket) key.conduit).accept(); _conduit_filehandle = _conduit.fileHandle(); _connections[_conduit_filehandle] = _conduit; Stdout.formatln("got conduit."); } catch (Exception e) { _selector.register(key.conduit, Event.Read); } if (key.isReadable()) { int count = (cast(SocketConduit) _conduit).read(buffer); if (count != IConduit.Eof) { _selector.register(key.conduit, Event.Write, key.attachment); Stdout.formatln("read input."); } else { _connections[_conduit_filehandle].shutdown(); _connections[_conduit_filehandle].detach(); } } if (key.isWritable()) { Stdout.formatln("start output."); _connections[_conduit_filehandle].write("output"); _selector.register(key.conduit, Event.Read, key.attachment); Stdout.formatln("wrote to output."); } if (key.isError() || key.isHangup() || key.isInvalidHandle()) { _selector.unregister(key.conduit); _connections[_conduit_filehandle].shutdown(); _connections[_conduit_filehandle].detach(); } } } } scope(exit) { _selector.close(); } }