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 }