Skip to content

Commit af39665

Browse files
authored
Simplify ConcurrentPool (#907)
1 parent f201248 commit af39665

File tree

1 file changed

+25
-44
lines changed

1 file changed

+25
-44
lines changed

driver-core/src/main/com/mongodb/internal/connection/ConcurrentPool.java

Lines changed: 25 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public class ConcurrentPool<T> implements Pool<T> {
5555
private final int maxSize;
5656
private final ItemFactory<T> itemFactory;
5757

58-
private final ConcurrentLinkedDeque<T> available = new ConcurrentLinkedDeque<T>();
58+
private final ConcurrentLinkedDeque<T> available = new ConcurrentLinkedDeque<>();
5959
private final StateAndPermits stateAndPermits;
6060
private final String poolClosedMessage;
6161

@@ -162,8 +162,6 @@ public T get() {
162162
*/
163163
@Override
164164
public T get(final long timeout, final TimeUnit timeUnit) {
165-
stateAndPermits.throwIfClosedOrPaused();
166-
167165
if (!stateAndPermits.acquirePermit(timeout, timeUnit)) {
168166
throw new MongoTimeoutException(String.format("Timeout waiting for a pooled item after %d %s", timeout, timeUnit));
169167
}
@@ -183,7 +181,6 @@ public T get(final long timeout, final TimeUnit timeUnit) {
183181
*/
184182
@Nullable
185183
T getImmediateUnfair() {
186-
stateAndPermits.throwIfClosedOrPaused();
187184
T element = null;
188185
if (stateAndPermits.acquirePermitImmediateUnfair()) {
189186
element = available.pollLast();
@@ -221,7 +218,6 @@ public void prune() {
221218
* Otherwise, the action must {@linkplain #release(Object) release} the item.
222219
*/
223220
public void ensureMinSize(final int minSize, final Consumer<T> initAndRelease) {
224-
stateAndPermits.throwIfClosedOrPaused();
225221
while (getCount() < minSize) {
226222
if (!stateAndPermits.acquirePermit(0, TimeUnit.MILLISECONDS)) {
227223
break;
@@ -284,12 +280,9 @@ public int getCount() {
284280
}
285281

286282
public String toString() {
287-
StringBuilder buf = new StringBuilder();
288-
buf.append("pool: ")
289-
.append(" maxSize: ").append(sizeToString(maxSize))
290-
.append(" availableCount ").append(getAvailableCount())
291-
.append(" inUseCount ").append(getInUseCount());
292-
return buf.toString();
283+
return "pool: maxSize: " + sizeToString(maxSize)
284+
+ " availableCount " + getAvailableCount()
285+
+ " inUseCount " + getInUseCount();
293286
}
294287

295288
/**
@@ -332,7 +325,7 @@ static boolean isPoolClosedException(final Throwable e) {
332325
@ThreadSafe
333326
private static final class StateAndPermits {
334327
private final Supplier<MongoServerUnavailableException> poolClosedExceptionSupplier;
335-
private final ReentrantReadWriteLock lock;
328+
private final ReentrantLock lock;
336329
private final Condition permitAvailableOrClosedOrPausedCondition;
337330
private volatile boolean paused;
338331
private volatile boolean closed;
@@ -373,8 +366,8 @@ private static final class StateAndPermits {
373366

374367
StateAndPermits(final int maxPermits, final Supplier<MongoServerUnavailableException> poolClosedExceptionSupplier) {
375368
this.poolClosedExceptionSupplier = poolClosedExceptionSupplier;
376-
lock = new ReentrantReadWriteLock(true);
377-
permitAvailableOrClosedOrPausedCondition = lock.writeLock().newCondition();
369+
lock = new ReentrantLock(true);
370+
permitAvailableOrClosedOrPausedCondition = lock.newCondition();
378371
paused = false;
379372
closed = false;
380373
this.maxPermits = maxPermits;
@@ -388,7 +381,7 @@ int permits() {
388381
}
389382

390383
boolean acquirePermitImmediateUnfair() {
391-
lockUnfair(lock.writeLock());
384+
lockUnfair(lock);
392385
try {
393386
throwIfClosedOrPaused();
394387
if (permits > 0) {
@@ -399,7 +392,7 @@ boolean acquirePermitImmediateUnfair() {
399392
return false;
400393
}
401394
} finally {
402-
lock.writeLock().unlock();
395+
lock.unlock();
403396
}
404397
}
405398

@@ -412,9 +405,9 @@ boolean acquirePermitImmediateUnfair() {
412405
boolean acquirePermit(final long timeout, final TimeUnit unit) throws MongoInterruptedException {
413406
long remainingNanos = unit.toNanos(timeout);
414407
if (waitersEstimate.get() == 0) {
415-
lockInterruptiblyUnfair(lock.writeLock());
408+
lockInterruptiblyUnfair(lock);
416409
} else {
417-
lockInterruptibly(lock.writeLock());
410+
lockInterruptibly(lock);
418411
}
419412
try {
420413
while (permits == 0
@@ -440,43 +433,43 @@ boolean acquirePermit(final long timeout, final TimeUnit unit) throws MongoInter
440433
permits--;
441434
return true;
442435
} finally {
443-
lock.writeLock().unlock();
436+
lock.unlock();
444437
}
445438
}
446439

447440
void releasePermit() {
448-
lockUnfair(lock.writeLock());
441+
lockUnfair(lock);
449442
try {
450443
assertTrue(permits < maxPermits);
451444
//noinspection NonAtomicOperationOnVolatileField
452445
permits++;
453446
permitAvailableOrClosedOrPausedCondition.signal();
454447
} finally {
455-
lock.writeLock().unlock();
448+
lock.unlock();
456449
}
457450
}
458451

459452
void pause(final Supplier<MongoException> causeSupplier) {
460-
lockUnfair(lock.writeLock());
453+
lockUnfair(lock);
461454
try {
462455
if (!paused) {
463456
this.paused = true;
464457
permitAvailableOrClosedOrPausedCondition.signalAll();
465458
}
466459
this.causeSupplier = assertNotNull(causeSupplier);
467460
} finally {
468-
lock.writeLock().unlock();
461+
lock.unlock();
469462
}
470463
}
471464

472465
void ready() {
473466
if (paused) {
474-
lockUnfair(lock.writeLock());
467+
lockUnfair(lock);
475468
try {
476469
this.paused = false;
477470
this.causeSupplier = null;
478471
} finally {
479-
lock.writeLock().unlock();
472+
lock.unlock();
480473
}
481474
}
482475
}
@@ -486,21 +479,23 @@ void ready() {
486479
*/
487480
boolean close() {
488481
if (!closed) {
489-
lockUnfair(lock.writeLock());
482+
lockUnfair(lock);
490483
try {
491484
if (!closed) {
492485
closed = true;
493486
permitAvailableOrClosedOrPausedCondition.signalAll();
494487
return true;
495488
}
496489
} finally {
497-
lock.writeLock().unlock();
490+
lock.unlock();
498491
}
499492
}
500493
return false;
501494
}
502495

503496
/**
497+
* This method must be called by a {@link Thread} that holds the {@link #lock}.
498+
*
504499
* @return {@code false} which means that the method did not throw.
505500
* The method returns to allow using it conveniently as part of a condition check when waiting on a {@link Condition}.
506501
* Short-circuiting operators {@code &&} and {@code ||} must not be used with this method to ensure that it is called.
@@ -514,14 +509,7 @@ boolean throwIfClosedOrPaused() {
514509
throw poolClosedExceptionSupplier.get();
515510
}
516511
if (paused) {
517-
lock.readLock().lock();
518-
try {
519-
if (paused) {
520-
throw assertNotNull(assertNotNull(causeSupplier).get());
521-
}
522-
} finally {
523-
lock.readLock().unlock();
524-
}
512+
throw assertNotNull(assertNotNull(causeSupplier).get());
525513
}
526514
return false;
527515
}
@@ -546,9 +534,9 @@ static void lockInterruptibly(final Lock lock) throws MongoInterruptedException
546534
}
547535
}
548536

549-
private static void lockInterruptiblyUnfair(final ReentrantReadWriteLock.WriteLock lock) throws MongoInterruptedException {
537+
private static void lockInterruptiblyUnfair(final ReentrantLock lock) throws MongoInterruptedException {
550538
throwIfInterrupted();
551-
// `WriteLock.tryLock` is unfair
539+
// `ReentrantLock.tryLock` is unfair
552540
if (!lock.tryLock()) {
553541
try {
554542
lock.lockInterruptibly();
@@ -566,13 +554,6 @@ static void lockUnfair(final ReentrantLock lock) {
566554
}
567555
}
568556

569-
private static void lockUnfair(final ReentrantReadWriteLock.WriteLock lock) {
570-
// `WriteLock.tryLock` is unfair
571-
if (!lock.tryLock()) {
572-
lock.lock();
573-
}
574-
}
575-
576557
private static void throwIfInterrupted() throws MongoInterruptedException {
577558
if (Thread.currentThread().isInterrupted()) {
578559
throw new MongoInterruptedException(null, new InterruptedException());

0 commit comments

Comments
 (0)