View Javadoc
1   /*
2    * This file is part of ***  M y C o R e  ***
3    * See http://www.mycore.de/ for details.
4    *
5    * MyCoRe is free software: you can redistribute it and/or modify
6    * it under the terms of the GNU General Public License as published by
7    * the Free Software Foundation, either version 3 of the License, or
8    * (at your option) any later version.
9    *
10   * MyCoRe is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   * GNU General Public License for more details.
14   *
15   * You should have received a copy of the GNU General Public License
16   * along with MyCoRe.  If not, see <http://www.gnu.org/licenses/>.
17   */
18  
19  package org.mycore.util.concurrent;
20  
21  import java.util.concurrent.locks.Lock;
22  import java.util.concurrent.locks.ReadWriteLock;
23  import java.util.concurrent.locks.ReentrantReadWriteLock;
24  import java.util.function.Supplier;
25  
26  /**
27   * A MCRReadWriteGuard acts like a {@link ReadWriteLock} but automatically wraps read and write operations accordingly.
28   * @author Thomas Scheffler (yagee)
29   */
30  public class MCRReadWriteGuard {
31  
32      private Lock readLock;
33  
34      private Lock writeLock;
35  
36      public MCRReadWriteGuard() {
37          this(new ReentrantReadWriteLock());
38      }
39  
40      public MCRReadWriteGuard(ReadWriteLock readWriteLock) {
41          readLock = readWriteLock.readLock();
42          writeLock = readWriteLock.writeLock();
43      }
44  
45      /**
46       * Executes the read operation while the read lock is locked.
47       * This is a sharable lock. Many <code>reader</code> can be executed simultaneously
48       * when no write operation is running.
49       * @param reader a read operation that should be guarded.
50       * @return result of {@link Supplier#get()}
51       */
52      public <T> T read(Supplier<T> reader) {
53          readLock.lock();
54          try {
55              return reader.get();
56          } finally {
57              readLock.unlock();
58          }
59      }
60  
61      /**
62       * Executes the write operation while the write lock is locked.
63       * This is an exclusive lock. So no other read or write operation
64       * can be executed while <code>operation</code> is running.
65       * @param operation
66       */
67      public void write(Runnable operation) {
68          writeLock.lock();
69          try {
70              operation.run();
71          } finally {
72              writeLock.unlock();
73          }
74      }
75  
76      public <T> T lazyLoad(Supplier<Boolean> check, Runnable operation, Supplier<T> reader) {
77          readLock.lock();
78          boolean holdsReadLock = true;
79          try {
80              if (check.get()) {
81                  holdsReadLock = false;
82                  readLock.unlock();
83                  write(operation);
84              }
85          } finally {
86              if (holdsReadLock) {
87                  readLock.unlock();
88              }
89          }
90          return reader.get();
91  
92      }
93  
94  }