Skip to content

Commit b6f72e7

Browse files
committed
Add builders for LockingVisitors implementations
1 parent da7c755 commit b6f72e7

File tree

3 files changed

+370
-22
lines changed

3 files changed

+370
-22
lines changed

src/changes/changes.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ The <action> type attribute can be add,update,fix,remove.
136136
<action type="add" dev="ggregory" due-to="Gary Gregory">Add org.apache.commons.lang3.concurrent.locks.LockingVisitors.reentrantLockVisitor(Object).</action>
137137
<action type="add" dev="ggregory" due-to="Gary Gregory">Add org.apache.commons.lang3.concurrent.locks.LockingVisitors.create(Object, ReentrantLock).</action>
138138
<action type="add" dev="ggregory" due-to="Gary Gregory">Add org.apache.commons.lang3.concurrent.locks.LockingVisitors.ReentrantLockVisitor.</action>
139+
<action type="add" dev="ggregory" due-to="Gary Gregory">Add builders for LockingVisitors implementations.</action>
139140
<!-- UPDATE -->
140141
<action type="update" dev="ggregory" due-to="Gary Gregory, Dependabot">Bump org.apache.commons:commons-parent from 73 to 85 #1267, #1277, #1283, #1288, #1302, #1377.</action>
141142
<action type="update" dev="ggregory" due-to="Gary Gregory, Dependabot">[site] Bump org.codehaus.mojo:taglist-maven-plugin from 3.1.0 to 3.2.1 #1300.</action>

src/main/java/org/apache/commons/lang3/concurrent/locks/LockingVisitors.java

Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.util.concurrent.locks.StampedLock;
2525
import java.util.function.Supplier;
2626

27+
import org.apache.commons.lang3.builder.AbstractSupplier;
2728
import org.apache.commons.lang3.function.Failable;
2829
import org.apache.commons.lang3.function.FailableConsumer;
2930
import org.apache.commons.lang3.function.FailableFunction;
@@ -94,6 +95,103 @@ public class LockingVisitors {
9495
*/
9596
public static class LockVisitor<O, L> {
9697

98+
/**
99+
* Builds {@link LockVisitor} instances.
100+
*
101+
* @param <O> the wrapped object type.
102+
* @param <L> the wrapped lock type.
103+
* @param <B> the builder type.
104+
* @since 3.18.0
105+
*/
106+
public static class LVBuilder<O, L, B extends LVBuilder<O, L, B>> extends AbstractSupplier<LockVisitor<O, L>, B, RuntimeException> {
107+
108+
/**
109+
* The lock object, untyped, since, for example {@link StampedLock} does not implement a locking interface in
110+
* Java 8.
111+
*/
112+
L lock;
113+
114+
/**
115+
* The guarded object.
116+
*/
117+
O object;
118+
119+
/**
120+
* Supplies the read lock, usually from the lock object.
121+
*/
122+
private Supplier<Lock> readLockSupplier;
123+
124+
/**
125+
* Supplies the write lock, usually from the lock object.
126+
*/
127+
private Supplier<Lock> writeLockSupplier;
128+
129+
/**
130+
* Constructs a new instance.
131+
*/
132+
public LVBuilder() {
133+
// empty
134+
}
135+
136+
@Override
137+
public LockVisitor<O, L> get() {
138+
return new LockVisitor<>(this);
139+
}
140+
141+
Supplier<Lock> getReadLockSupplier() {
142+
return readLockSupplier;
143+
}
144+
145+
146+
Supplier<Lock> getWriteLockSupplier() {
147+
return writeLockSupplier;
148+
}
149+
150+
/**
151+
* Set the lock used from accept methods.
152+
*
153+
* @param lock the lock.
154+
* @return {@code this} instance.
155+
*/
156+
public B setLock(final L lock) {
157+
this.lock = lock;
158+
return asThis();
159+
}
160+
161+
/**
162+
* Set the resource.
163+
*
164+
* @param object the resource.
165+
* @return {@code this} instance.
166+
*/
167+
public B setObject(final O object) {
168+
this.object = object;
169+
return asThis();
170+
}
171+
172+
/**
173+
* Supplies the read lock.
174+
*
175+
* @param readLockSupplier Supplies the read lock.
176+
* @return {@code this} instance.
177+
*/
178+
public B setReadLockSupplier(final Supplier<Lock> readLockSupplier) {
179+
this.readLockSupplier = readLockSupplier;
180+
return asThis();
181+
}
182+
183+
/**
184+
* Supplies the write lock.
185+
*
186+
* @param writeLockSupplier Supplies the write lock.
187+
* @return {@code this} instance.
188+
*/
189+
public B setWriteLockSupplier(final Supplier<Lock> writeLockSupplier) {
190+
this.writeLockSupplier = writeLockSupplier;
191+
return asThis();
192+
}
193+
}
194+
97195
/**
98196
* The lock object, untyped, since, for example {@link StampedLock} does not implement a locking interface in
99197
* Java 8.
@@ -115,6 +213,18 @@ public static class LockVisitor<O, L> {
115213
*/
116214
private final Supplier<Lock> writeLockSupplier;
117215

216+
/**
217+
* Constructs an instance from a builder.
218+
*
219+
* @param builder The builder.
220+
*/
221+
private LockVisitor(final LVBuilder<O, L, ?> builder) {
222+
this.object = Objects.requireNonNull(builder.object, "object");
223+
this.lock = Objects.requireNonNull(builder.lock, "lock");
224+
this.readLockSupplier = Objects.requireNonNull(builder.readLockSupplier, "readLockSupplier");
225+
this.writeLockSupplier = Objects.requireNonNull(builder.writeLockSupplier, "writeLockSupplier");
226+
}
227+
118228
/**
119229
* Constructs an instance.
120230
*
@@ -316,6 +426,54 @@ protected <T> T lockApplyUnlock(final Supplier<Lock> lockSupplier, final Failabl
316426
*/
317427
public static class ReadWriteLockVisitor<O> extends LockVisitor<O, ReadWriteLock> {
318428

429+
/**
430+
* Builds {@link LockVisitor} instances.
431+
*
432+
* @param <O> the wrapped object type.
433+
* @since 3.18.0
434+
*/
435+
public static class Builder<O> extends LVBuilder<O, ReadWriteLock, Builder<O>> {
436+
437+
/**
438+
* Constructs a new instance.
439+
*/
440+
public Builder() {
441+
// empty
442+
}
443+
444+
@Override
445+
public ReadWriteLockVisitor<O> get() {
446+
return new ReadWriteLockVisitor<>(this);
447+
}
448+
449+
@Override
450+
public Builder<O> setLock(final ReadWriteLock readWriteLock) {
451+
setReadLockSupplier(readWriteLock::readLock);
452+
setWriteLockSupplier(readWriteLock::writeLock);
453+
return super.setLock(readWriteLock);
454+
}
455+
}
456+
457+
/**
458+
* Creates a new builder.
459+
*
460+
* @param <O> the wrapped object type.
461+
* @return a new builder.
462+
* @since 3.18.0
463+
*/
464+
public static <O> Builder<O> builder() {
465+
return new Builder<>();
466+
}
467+
468+
/**
469+
* Constructs a new instance from a builder.
470+
*
471+
* @param builder a builder.
472+
*/
473+
private ReadWriteLockVisitor(final Builder<O> builder) {
474+
super(builder);
475+
}
476+
319477
/**
320478
* Creates a new instance with the given locked object. This constructor is supposed to be used for subclassing
321479
* only. In general, it is suggested to use {@link LockingVisitors#stampedLockVisitor(Object)} instead.
@@ -326,6 +484,7 @@ public static class ReadWriteLockVisitor<O> extends LockVisitor<O, ReadWriteLock
326484
protected ReadWriteLockVisitor(final O object, final ReadWriteLock readWriteLock) {
327485
super(object, readWriteLock, readWriteLock::readLock, readWriteLock::writeLock);
328486
}
487+
329488
}
330489

331490
/**
@@ -340,6 +499,56 @@ protected ReadWriteLockVisitor(final O object, final ReadWriteLock readWriteLock
340499
*/
341500
public static class ReentrantLockVisitor<O> extends LockVisitor<O, ReentrantLock> {
342501

502+
/**
503+
* Builds {@link LockVisitor} instances.
504+
*
505+
* @param <O> the wrapped object type.
506+
* @since 3.18.0
507+
*/
508+
public static class Builder<O> extends LVBuilder<O, ReentrantLock, Builder<O>> {
509+
510+
/**
511+
* Constructs a new instance.
512+
*/
513+
public Builder() {
514+
// empty
515+
}
516+
517+
@Override
518+
public ReentrantLockVisitor<O> get() {
519+
return new ReentrantLockVisitor<>(this);
520+
}
521+
522+
523+
@Override
524+
public Builder<O> setLock(final ReentrantLock reentrantLock) {
525+
setReadLockSupplier(() -> reentrantLock);
526+
setWriteLockSupplier(() -> reentrantLock);
527+
return super.setLock(reentrantLock);
528+
}
529+
}
530+
531+
/**
532+
* Creates a new builder.
533+
*
534+
* @param <O> the wrapped object type.
535+
* @return a new builder.
536+
* @since 3.18.0
537+
*/
538+
public static <O> Builder<O> builder() {
539+
return new Builder<>();
540+
}
541+
542+
/**
543+
* Constructs a new instance from a builder.
544+
*
545+
* @param builder a builder.
546+
*/
547+
private ReentrantLockVisitor(final Builder<O> builder) {
548+
super(builder);
549+
}
550+
551+
343552
/**
344553
* Creates a new instance with the given locked object. This constructor is supposed to be used for subclassing
345554
* only. In general, it is suggested to use {@link LockingVisitors#reentrantLockVisitor(Object)} instead.
@@ -363,6 +572,55 @@ protected ReentrantLockVisitor(final O object, final ReentrantLock reentrantLock
363572
*/
364573
public static class StampedLockVisitor<O> extends LockVisitor<O, StampedLock> {
365574

575+
/**
576+
* Builds {@link LockVisitor} instances.
577+
*
578+
* @param <O> the wrapped object type.
579+
* @since 3.18.0
580+
*/
581+
public static class Builder<O> extends LVBuilder<O, StampedLock, Builder<O>> {
582+
583+
/**
584+
* Constructs a new instance.
585+
*/
586+
public Builder() {
587+
// empty
588+
}
589+
590+
@Override
591+
public StampedLockVisitor<O> get() {
592+
return new StampedLockVisitor<>(this);
593+
}
594+
595+
596+
@Override
597+
public Builder<O> setLock(final StampedLock stampedLock) {
598+
setReadLockSupplier(stampedLock::asReadLock);
599+
setWriteLockSupplier(stampedLock::asWriteLock);
600+
return super.setLock(stampedLock);
601+
}
602+
}
603+
604+
/**
605+
* Creates a new builder.
606+
*
607+
* @param <O> the wrapped object type.
608+
* @return a new builder.
609+
* @since 3.18.0
610+
*/
611+
public static <O> Builder<O> builder() {
612+
return new Builder<>();
613+
}
614+
615+
/**
616+
* Constructs a new instance from a builder.
617+
*
618+
* @param builder a builder.
619+
*/
620+
private StampedLockVisitor(final Builder<O> builder) {
621+
super(builder);
622+
}
623+
366624
/**
367625
* Creates a new instance with the given locked object. This constructor is supposed to be used for subclassing
368626
* only. In general, it is suggested to use {@link LockingVisitors#stampedLockVisitor(Object)} instead.

0 commit comments

Comments
 (0)