/** * Sets value for this sync. * * @param x Value. * @param e Exception. */ public void set(@Nullable X x, @Nullable RuntimeException e) { this.x = x; this.e = e; boolean res = compareAndSetState(-1, 0); // Set finish state. assert res; }
/** * Releases this sync after update. * * @return {@code true} If this sync was flipped and current thread was the last updater. */ public boolean releaseAfterUpdate() { for (;;) { int curr = getState(); assert curr != 0; int next = curr < 0 ? curr + 1 : curr - 1; assert next != 0; if (compareAndSetState(curr, next)) return next == -1; // -1 means that sync was flipped and we are the last updater. } }
/** * Flips this sync so that no subsequent updates can happen. * * @return {@code true} If there are no updaters currently in progress to wait. */ public boolean flip() { for (;;) { int curr = getState(); if (curr <= 0) return false; if (compareAndSetState(curr, -curr)) return curr == 1; // 1 means no active updaters, we should take snapshot ourself. } }
/** * Tries to acquire this sync for update. Multiple threads allowed to do update at the same time. * * @return {@code true} If operation succeeded. */ public boolean tryAcquireForUpdate() { for (;;) { int curr = getState(); if (curr <= 0) // We are flipped or finished. return false; if (compareAndSetState(curr, curr + 1)) return true; } }
/** {@inheritDoc} */ @Override protected final int tryAcquireShared(int ignored) { return getState() == 0 ? 1 : -1; // 0 means x already set and we should not block any threads. }
/** * Must be called before update begin. */ public void beginUpdate() { Sync<X> sync0; while (!(sync0 = sync).tryAcquireForUpdate()) sync0.awaitResult(); }
/** * Sets value for this sync. * * @param x Value. * @param e Exception. */ public void set(@Nullable X x, @Nullable RuntimeException e) { this.x = x; this.e = e; boolean res = compareAndSetState(-1, 0); // Set finish state. assert res; }
/** * Wakes up all queued on this sync threads and allows them to proceed. */ public void signalAll() { releaseShared(1); }
/** * Signal that update operation finished. */ public void endUpdate() { Sync<X> sync0 = sync; if (sync0.releaseAfterUpdate()) takeSnapshotAndReplaceSync(sync0); }
/** * Wait until x or e will be set. */ public void awaitResult() { acquireShared(1); }
/** * Waits until value will be set and returns it. * * @return Value which was set using {@link #set(Object, RuntimeException)}. */ public X get() { awaitResult(); if (e != null) throw e; return x; }
/** * Releases this sync after update. * * @return {@code true} If this sync was flipped and current thread was the last updater. */ public boolean releaseAfterUpdate() { for (;;) { int curr = getState(); assert curr != 0; int next = curr < 0 ? curr + 1 : curr - 1; assert next != 0; if (compareAndSetState(curr, next)) return next == -1; // -1 means that sync was flipped and we are the last updater. } }
/** * Tries to acquire this sync for update. Multiple threads allowed to do update at the same time. * * @return {@code true} If operation succeeded. */ public boolean tryAcquireForUpdate() { for (;;) { int curr = getState(); if (curr <= 0) // We are flipped or finished. return false; if (compareAndSetState(curr, curr + 1)) return true; } }
/** * Flips this sync so that no subsequent updates can happen. * * @return {@code true} If there are no updaters currently in progress to wait. */ public boolean flip() { for (;;) { int curr = getState(); if (curr <= 0) return false; if (compareAndSetState(curr, -curr)) return curr == 1; // 1 means no active updaters, we should take snapshot ourself. } }
/** {@inheritDoc} */ @Override protected final int tryAcquireShared(int ignored) { return getState() == 0 ? 1 : -1; // 0 means x already set and we should not block any threads. }
/** * Waits until value will be set and returns it. * * @return Value which was set using {@link #set(Object, RuntimeException)}. */ public X get() { awaitResult(); if (e != null) throw e; return x; }
/** * Wait until x or e will be set. */ public void awaitResult() { acquireShared(1); }