View Javadoc

1   package com.atlassian.vcache.internal.core.service;
2   
3   import java.util.concurrent.TimeUnit;
4   import java.util.concurrent.locks.AbstractQueuedSynchronizer;
5   
6   /**
7    * A useful synchronization construct for ensuring the correct behaviour of cache implementations.
8    * <p>
9    * The one-shot latch is initially held by the thread that creates it and must be explicitly
10   * released by it.
11   * </p>
12   *
13   * @since 1.0.0
14   */
15  class OneShotLatch {
16      private final Sync sync = new Sync();
17  
18      public boolean isHeldByCurrentThread() {
19          return sync.isHeldByCurrentThread();
20      }
21  
22      public void release() {
23          sync.release(0);
24      }
25  
26      public void await() {
27          sync.acquireShared(0);
28      }
29  
30      public boolean await(long timeout, TimeUnit unit) throws InterruptedException {
31          return sync.tryAcquireSharedNanos(0, unit.toNanos(timeout));
32      }
33  
34      @Override
35      public String toString() {
36          return "OneShotLatch[sync=" + sync + ']';
37      }
38  
39  
40      static class Sync extends AbstractQueuedSynchronizer {
41          private static final int STATE_UNAVAILABLE = -1;
42          private static final int STATE_RELEASED = 1;
43  
44          Sync() {
45              setState(STATE_UNAVAILABLE);
46              setExclusiveOwnerThread(Thread.currentThread());
47          }
48  
49          boolean isHeldByCurrentThread() {
50              return getExclusiveOwnerThread() == Thread.currentThread();
51          }
52  
53          @Override
54          protected boolean tryRelease(int ignored) {
55              if (!isHeldByCurrentThread()) {
56                  throw new IllegalMonitorStateException(toString());
57              }
58  
59              setExclusiveOwnerThread(null);
60              setState(STATE_RELEASED);
61              return true;
62          }
63  
64          @Override
65          protected int tryAcquireShared(int ignored) {
66              final int state = getState();
67              if (state == STATE_UNAVAILABLE && isHeldByCurrentThread()) {
68                  throw new IllegalMonitorStateException(toString());
69              }
70              return state;
71          }
72  
73          @Override
74          public String toString() {
75              return "Sync[state=" + getState() + "; owner=" + getExclusiveOwnerThread() + ']';
76          }
77      }
78  }