protected QueueChannel(BasicQueue<Message> queue, OverflowPolicy overflowPolicy, boolean singleProducer, boolean singleConsumer) { this.queue = queue; if (!singleConsumer || queue instanceof CircularBuffer) this.sync = new SimpleConditionSynchronizer(this); else this.sync = new OwnedSynchronizer(this); this.overflowPolicy = overflowPolicy; this.sendersSync = overflowPolicy == OverflowPolicy.BLOCK ? new SimpleConditionSynchronizer(this) : null; this.singleProducer = singleProducer; this.singleConsumer = singleConsumer; }
private void set0(V value) { final SimpleConditionSynchronizer s = sync; if (s == null) throw new IllegalStateException("Value has already been set (and can only be set once)"); this.value = value; sync = null; // must be done before signal this.f = null; s.signalAll(); }
/** * Returns the delayed value, blocking until it has been set. * * @return the value * @throws InterruptedException */ @Override @Suspendable public V get() throws InterruptedException { try { final SimpleConditionSynchronizer s = sync; if (s != null) { Object token = s.register(); try { for (int i = 0; sync != null; i++) s.await(i); } finally { s.unregister(token); } } if (t != null) throw new RuntimeExecutionException(t); return value; } catch (SuspendExecution e) { throw new AssertionError(e); } }
final SimpleConditionSynchronizer s = sync; if (s != null) { Object token = s.register(); try { final long start = System.nanoTime(); final long deadline = start + left; for (int i = 0; sync != null; i++) { s.awaitNanos(i, left); if (sync == null) break; s.unregister(token);
@Override public void signalAll() { for (Strand s : waiters) { record("signalAll", "%s signalling %s", this, s); Strand.unpark(s, owner); } }
@Override public Object register() { final Strand currentStrand = Strand.currentStrand(); record("register", "%s register %s", this, currentStrand); waiters.add(currentStrand); return null; }
@Override public void unregister(Object registrationToken) { final Strand currentStrand = Strand.currentStrand(); record("unregister", "%s unregister %s", this, currentStrand); if (!waiters.remove(currentStrand)) throw new IllegalMonitorStateException(); }
private void setException0(Throwable t) { final SimpleConditionSynchronizer s = sync; if (s == null) throw new IllegalStateException("Value has already been set (and can only be set once)"); this.t = t; sync = null; // must be done before signal this.f = null; s.signalAll(); }
@Override public void signal() { /* * We must wake up the first waiter that is actually parked. Otherwise, by the time the awakened waiter calls * unregister(), another one may block, and we may need to wake that one. */ for (final Strand s : waiters) { if (s.isFiber()) { if (FiberControl.unpark((Fiber) s, owner)) { record("signal", "%s signalled %s", this, s); return; } } else { // TODO: We can't tell (atomically) if a thread is actually parked, so we'll wake them all up. // We may consider a more complex solution, a-la AbstractQueuedSynchronizer for threads // (i.e. with a wrapper node, containing the state) record("signal", "%s signalling %s", this, s); Strand.unpark(s, owner); } } } }