X-Git-Url: http://dolda2000.com/gitweb/?a=blobdiff_plain;f=src%2Fjagi%2Fevent%2FDriver.java;h=59f54a3b72e634a700c2bad959d3780e477d4a55;hb=12032480fba70f0521b0ec7ef7bc8db10fc87636;hp=c9ca63856081003d49e1eec3b86e7e24cf148874;hpb=aac2f975859e9b0bbbf582c4d84bebccd2e27e51;p=jagi.git diff --git a/src/jagi/event/Driver.java b/src/jagi/event/Driver.java index c9ca638..59f54a3 100644 --- a/src/jagi/event/Driver.java +++ b/src/jagi/event/Driver.java @@ -26,7 +26,18 @@ public class Driver { current.set(this); w.handle(evs); } catch(Throwable t) { - error(w, t); + error(w, t, "handling event"); + } finally { + current.remove(); + } + } + + protected void close(Watcher w) { + try { + current.set(this); + w.close(); + } catch(Throwable t) { + error(w, t, "closing"); } finally { current.remove(); } @@ -36,8 +47,8 @@ public class Driver { worker.submit(task); } - protected void error(Watcher w, Throwable t) { - hlog.log(Level.WARNING, w + ": uncaught error when handling event", t); + protected void error(Watcher w, Throwable t, String thing) { + hlog.log(Level.WARNING, w + ": uncaught error when " + thing, t); remove(w); } @@ -59,6 +70,8 @@ public class Driver { } void handle(Watcher w, int evs) { + if(!watching.containsKey(w)) + return; try { pause(w); submit(() -> { @@ -88,8 +101,8 @@ public class Driver { boolean quit = false; Throwable error = null; try { + double now = time(); while(true) { - double now = time(); long timeout = 0; synchronized(selectors) { Double first = timeheap.keypeek(); @@ -99,7 +112,7 @@ public class Driver { return; } if(first != null) - timeout = (long)Math.ceil((first - now) * 1000); + timeout = Math.max((long)Math.ceil((first - now) * 1000), 0); } poll.selectedKeys().clear(); try { @@ -109,6 +122,13 @@ public class Driver { } for(SelectionKey key : poll.selectedKeys()) handle((Watcher)key.attachment(), key.readyOps()); + now = time(); + while(true) { + Double first = timeheap.keypeek(); + if((first == null) || (first > now)) + break; + handle(timeheap.remove(), 0); + } } } catch(Throwable t) { error = t; @@ -138,7 +158,7 @@ public class Driver { int evs = w.events(); double timeout = w.timeout(); boolean hastime = timeout < Double.POSITIVE_INFINITY; - if((evs == 0) && !hastime) { + if(evs < 0) { remove(w); return; } @@ -154,10 +174,11 @@ public class Driver { int evs = w.events(); double timeout = w.timeout(); boolean hastime = timeout < Double.POSITIVE_INFINITY; - if((evs == 0) && !hastime) { - w.close(); + if(evs < 0) { + submit(() -> close(w)); return; } + w.added(Driver.this); try { watching.put(w, ch.register(poll, evs, w)); } catch(ClosedChannelException e) { @@ -178,7 +199,7 @@ public class Driver { throw(new RuntimeException(w + ": inconsistent internal state")); if(wc == null) throw(new IllegalStateException(w + ": not registered")); - w.close(); + submit(() -> close(w)); poll.wakeup(); } @@ -189,7 +210,7 @@ public class Driver { int evs = w.events(); double timeout = w.timeout(); boolean hastime = timeout < Double.POSITIVE_INFINITY; - if((evs == 0) && !hastime) { + if(evs < 0) { remove(w); return; }