This is an automated email from the ASF dual-hosted git repository. ggregory pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-lang.git
The following commit(s) were added to refs/heads/master by this push: new ed0f5be Reimplement such that locking and unlocking take place in the same method. ed0f5be is described below commit ed0f5bea111c449fa17478d7e0c7c37c3ede3863 Author: Gary Gregory <garydgreg...@gmail.com> AuthorDate: Thu Jun 18 12:48:46 2020 -0400 Reimplement such that locking and unlocking take place in the same method. --- .../org/apache/commons/lang3/concurrent/Locks.java | 61 ++++++++++++---------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/src/main/java/org/apache/commons/lang3/concurrent/Locks.java b/src/main/java/org/apache/commons/lang3/concurrent/Locks.java index f78a9dd..f8ecae9 100644 --- a/src/main/java/org/apache/commons/lang3/concurrent/Locks.java +++ b/src/main/java/org/apache/commons/lang3/concurrent/Locks.java @@ -18,36 +18,36 @@ package org.apache.commons.lang3.concurrent; import java.util.Objects; import java.util.concurrent.locks.StampedLock; +import java.util.function.LongSupplier; import org.apache.commons.lang3.function.Failable; import org.apache.commons.lang3.function.FailableConsumer; import org.apache.commons.lang3.function.FailableFunction; - /** * Utility class for working with {@link java.util.concurrent.locks.Lock locked objects}. Locked objects are an * alternative to synchronization. * - * Locking is preferable, if there is a distinction between read access (multiple threads may have read - * access concurrently), and write access (only one thread may have write access at any given time. - * In comparison, synchronization doesn't support read access, because synchronized access is exclusive. + * Locking is preferable, if there is a distinction between read access (multiple threads may have read access + * concurrently), and write access (only one thread may have write access at any given time. In comparison, + * synchronization doesn't support read access, because synchronized access is exclusive. * * Using this class is fairly straightforward: * <ol> - * <li>While still in single thread mode, create an instance of {@link Locks.Lock} by calling - * {@link #lock(Object)}, passing the object, which needs to be locked. Discard all - * references to the locked object. Instead, use references to the lock.</li> - * <li>If you want to access the locked object, create a {@link FailableConsumer}. The consumer - * will receive the locked object as a parameter. For convenience, the consumer may be - * implemented as a Lambda. Then invoke {@link Locks.Lock#runReadLocked(FailableConsumer)}, - * or {@link Locks.Lock#runWriteLocked(FailableConsumer)}, passing the consumer.</li> - * <li>As an alternative, if you need to produce a result object, you may use a - * {@link FailableFunction}. This function may also be implemented as a Lambda. To - * have the function executed, invoke {@link Locks.Lock#callReadLocked(FailableFunction)}, or - * {@link Locks.Lock#callWriteLocked(FailableFunction)}.</li> + * <li>While still in single thread mode, create an instance of {@link Locks.Lock} by calling {@link #lock(Object)}, + * passing the object, which needs to be locked. Discard all references to the locked object. Instead, use references to + * the lock.</li> + * <li>If you want to access the locked object, create a {@link FailableConsumer}. The consumer will receive the locked + * object as a parameter. For convenience, the consumer may be implemented as a Lambda. Then invoke + * {@link Locks.Lock#runReadLocked(FailableConsumer)}, or {@link Locks.Lock#runWriteLocked(FailableConsumer)}, passing + * the consumer.</li> + * <li>As an alternative, if you need to produce a result object, you may use a {@link FailableFunction}. This function + * may also be implemented as a Lambda. To have the function executed, invoke + * {@link Locks.Lock#callReadLocked(FailableFunction)}, or {@link Locks.Lock#callWriteLocked(FailableFunction)}.</li> * </ol> * * Example: A thread safe logger class. + * * <pre> * public class SimpleLogger { * private final Lock<PrintStream> lock; @@ -65,6 +65,7 @@ import org.apache.commons.lang3.function.FailableFunction; * lock.runWriteLocked((ps) -> { ps.write(buffer); ps.println(); }); * } * </pre> + * * @since 3.11 */ public class Locks { @@ -73,40 +74,42 @@ public class Locks { private final O lockedObject; private final StampedLock lock = new StampedLock(); - public Lock(O lockedObject) { + public Lock(final O lockedObject) { this.lockedObject = Objects.requireNonNull(lockedObject, "Locked Object"); } - public void runReadLocked(FailableConsumer<O, ?> consumer) { - acceptLocked(lock.readLock(), consumer); + public void runReadLocked(final FailableConsumer<O, ?> consumer) { + acceptLocked(() -> lock.readLock(), consumer); } - public void runWriteLocked(FailableConsumer<O, ?> consumer) { - acceptLocked(lock.writeLock(), consumer); + public void runWriteLocked(final FailableConsumer<O, ?> consumer) { + acceptLocked(() -> lock.writeLock(), consumer); } - public <T> T callReadLocked(FailableFunction<O, T, ?> function) { - return applyLocked(lock.readLock(), function); + public <T> T callReadLocked(final FailableFunction<O, T, ?> function) { + return applyLocked(() -> lock.readLock(), function); } - public <T> T callWriteLocked(FailableFunction<O, T, ?> function) { - return applyLocked(lock.writeLock(), function); + public <T> T callWriteLocked(final FailableFunction<O, T, ?> function) { + return applyLocked(() -> lock.writeLock(), function); } - protected void acceptLocked(long stamp, FailableConsumer<O, ?> consumer) { + protected void acceptLocked(final LongSupplier stampSupplier, final FailableConsumer<O, ?> consumer) { + final long stamp = stampSupplier.getAsLong(); try { consumer.accept(lockedObject); - } catch (Throwable t) { + } catch (final Throwable t) { throw Failable.rethrow(t); } finally { lock.unlock(stamp); } } - protected <T> T applyLocked(long stamp, FailableFunction<O, T, ?> function) { + protected <T> T applyLocked(final LongSupplier stampSupplier, final FailableFunction<O, T, ?> function) { + final long stamp = stampSupplier.getAsLong(); try { return function.apply(lockedObject); - } catch (Throwable t) { + } catch (final Throwable t) { throw Failable.rethrow(t); } finally { lock.unlock(stamp); @@ -114,7 +117,7 @@ public class Locks { } } - public static <O extends Object> Locks.Lock<O> lock(O object) { + public static <O extends Object> Locks.Lock<O> lock(final O object) { return new Locks.Lock<>(object); } }