View Javadoc

1   package com.atlassian.vcache.internal.core.service;
2   
3   import com.atlassian.vcache.VCacheException;
4   import org.slf4j.Logger;
5   import org.slf4j.LoggerFactory;
6   
7   import java.time.Duration;
8   import java.util.concurrent.TimeUnit;
9   import java.util.concurrent.locks.ReentrantLock;
10  import java.util.function.Supplier;
11  
12  import static java.util.Objects.requireNonNull;
13  
14  /**
15   * A lock for caches. It provides the common logic, such as timeouts for acquiring locks.
16   * @since 1.9.0
17   */
18  public class VCacheLock {
19      private static final Logger log = LoggerFactory.getLogger(VCacheLock.class);
20  
21      private final ReentrantLock lock = new ReentrantLock();
22      private final String cacheName;
23      private final long lockTimeoutMillis;
24  
25      public VCacheLock(String cacheName, Duration lockTimeout) {
26          this.cacheName = requireNonNull(cacheName);
27          this.lockTimeoutMillis = lockTimeout.toMillis();
28      }
29  
30      public <R> R withLock(Supplier<R> supplier) {
31          lockWithTimeout();
32          try {
33              return supplier.get();
34          } finally {
35              lock.unlock();
36          }
37      }
38  
39      public void withLock(Runnable runner) {
40          lockWithTimeout();
41          try {
42              runner.run();
43          } finally {
44              lock.unlock();
45          }
46      }
47  
48      private void lockWithTimeout() {
49          try {
50              if (!lock.tryLock(lockTimeoutMillis, TimeUnit.MILLISECONDS)) {
51                  log.warn("Timed out waiting for lock on cache: {}", cacheName);
52                  throw new VCacheException("Timed out waiting for lock on cache: " + cacheName);
53              }
54          } catch (InterruptedException e) {
55              Thread.interrupted();
56              log.warn("Interrupted whilst waiting for a lock on cache: ", cacheName, e);
57              throw new VCacheException("Interrupted waiting for lock on cache: " + cacheName, e);
58          }
59      }
60  }