summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
1203248)
This seems very needlessly complex for something which shouldn't even
have to be an issue, but I can't obviously see how else to handle it,
but also not really what the whole point of selectors "cancelled-sets"
is.
final Map<Watcher, SelectionKey> watching = new IdentityHashMap<>();
final Heap<Watcher, Double> timeheap = new Heap<>(Comparator.naturalOrder());
final Map<Watcher, Object> paused = new IdentityHashMap<>();
final Map<Watcher, SelectionKey> watching = new IdentityHashMap<>();
final Heap<Watcher, Double> timeheap = new Heap<>(Comparator.naturalOrder());
final Map<Watcher, Object> paused = new IdentityHashMap<>();
+ final Collection<SelectionKey> cancelled = new HashSet<>();
SelectPool(SelectorProvider provider) {
this.provider = provider;
SelectPool(SelectorProvider provider) {
this.provider = provider;
return;
}
if(first != null)
return;
}
if(first != null)
- timeout = Math.max((long)Math.ceil((first - now) * 1000), 0);
+ timeout = Math.max((long)Math.ceil((first - now) * 1000), 1);
+ Collection<SelectionKey> precancelled;
+ synchronized(cancelled) {
+ precancelled = new ArrayList<>(cancelled);
+ }
+ if(!precancelled.isEmpty())
+ timeout = 1;
poll.selectedKeys().clear();
try {
poll.select(timeout);
} catch(IOException e) {
throw(new RuntimeException(e));
}
poll.selectedKeys().clear();
try {
poll.select(timeout);
} catch(IOException e) {
throw(new RuntimeException(e));
}
+ if(!precancelled.isEmpty()) {
+ synchronized(cancelled) {
+ cancelled.removeAll(precancelled);
+ cancelled.notifyAll();
+ }
+ }
for(SelectionKey key : poll.selectedKeys())
handle((Watcher)key.attachment(), key.readyOps());
now = time();
for(SelectionKey key : poll.selectedKeys())
handle((Watcher)key.attachment(), key.readyOps());
now = time();
SelectionKey wc = watching.remove(w);
Object tc = timeheap.remove(w);
Object pc = paused.remove(w);
SelectionKey wc = watching.remove(w);
Object tc = timeheap.remove(w);
Object pc = paused.remove(w);
- if(wc != null)
- wc.cancel();
+ if(wc != null) {
+ synchronized(cancelled) {
+ cancelled.add(wc);
+ wc.cancel();
+ poll.wakeup();
+ boolean irq = false;
+ while(cancelled.contains(wc)) {
+ try {
+ cancelled.wait();
+ } catch(InterruptedException e) {
+ irq = true;
+ }
+ }
+ if(irq)
+ Thread.currentThread().interrupt();
+ }
+ }
if(((wc != null) || (tc != null)) && (pc != null))
throw(new RuntimeException(w + ": inconsistent internal state"));
if(wc == null)
throw(new IllegalStateException(w + ": not registered"));
submit(() -> close(w));
if(((wc != null) || (tc != null)) && (pc != null))
throw(new RuntimeException(w + ": inconsistent internal state"));
if(wc == null)
throw(new IllegalStateException(w + ": not registered"));
submit(() -> close(w));
}
void update(Watcher w) {
}
void update(Watcher w) {