@@ -26,7 +26,7 @@ import scala.concurrent.{BlockContext, CanAwait}
26
26
import scala .concurrent .duration .{Duration , FiniteDuration }
27
27
28
28
import java .lang .Long .MIN_VALUE
29
- import java .util .concurrent .{ ThreadLocalRandom , TimeUnit }
29
+ import java .util .concurrent .ThreadLocalRandom
30
30
import java .util .concurrent .atomic .AtomicBoolean
31
31
32
32
import WorkerThread .{Metrics , TransferState }
@@ -713,7 +713,7 @@ private[effect] final class WorkerThread[P <: AnyRef](
713
713
if (blocking) {
714
714
// The worker thread was blocked before. It is no longer part of the
715
715
// core pool and needs to be cached.
716
- val stateToTransfer = transferState
716
+
717
717
// First of all, remove the references to data structures of the core
718
718
// pool because they have already been transferred to another thread
719
719
// which took the place of this one.
@@ -727,32 +727,31 @@ private[effect] final class WorkerThread[P <: AnyRef](
727
727
transferState = null
728
728
729
729
try {
730
- // Try to transfer this thread via the stateTransferQueue to be picked up
730
+ // Try to transfer this thread via the cached threads data structure, to be picked up
731
731
// by another thread in the future.
732
- val st = stateToTransfer
733
732
val len = runtimeBlockingExpiration.length
734
733
val unit = runtimeBlockingExpiration.unit
735
- val timeoutNanos = unit.toNanos(len)
736
734
737
- if (pool.stateTransferQueue.offer(st)) {
738
- // Someone accepted the transfer of this thread and will transfer the state soon.
739
- val newState = pool.stateTransferQueue.poll(timeoutNanos, TimeUnit .NANOSECONDS )
740
- if (newState ne null ) {
741
- init(newState)
742
- } else {
743
- // The timeout elapsed and no one woke up this thread. It's time to exit.
744
- pool.blockedWorkerThreadCounter.decrementAndGet()
745
- return
746
- }
735
+ // Try to poll for a new state from the transfer queue
736
+ val newState = pool.transferStateQueue.poll(len, unit)
737
+
738
+ if (newState ne null ) {
739
+ // Got a state to take over
740
+ init(newState)
741
+
747
742
} else {
748
- // Nobody polling, spawn new replacement was done in prepareForBlocking
743
+ // No state to take over after timeout, exit
749
744
pool.blockedWorkerThreadCounter.decrementAndGet()
745
+ // Remove from blocker threads map if present
746
+ pool.blockerThreads.remove(this )
750
747
return
751
748
}
752
749
} catch {
753
750
case _ : InterruptedException =>
754
751
// This thread was interrupted while cached. This should only happen
755
- // during the shutdown of the pool. Nothing else to be done, just exit.
752
+ // during the shutdown of the pool. Nothing else to be done, just
753
+ // exit.
754
+ pool.blockerThreads.remove(this )
756
755
return
757
756
}
758
757
}
@@ -935,16 +934,18 @@ private[effect] final class WorkerThread[P <: AnyRef](
935
934
// Set the name of this thread to a blocker prefixed name.
936
935
setName(s " $prefix- $nameIndex" )
937
936
938
- val ts = transferState
939
- val available = pool.stateTransferQueue.poll(0 , TimeUnit .MILLISECONDS )
940
- if (available ne null ) {
941
- // There is a cached worker thread that can be reused.
942
- val idx = index
943
- pool.replaceWorker(idx, this )
944
- // Transfer the data structures to the cached thread and wake it up.
945
- ts.index = idx
946
- ts.tick = tick + 1
947
- val _ = pool.stateTransferQueue.offer(ts)
937
+ val idx = index
938
+
939
+ // Prepare the transfer state
940
+ transferState.index = idx
941
+ transferState.tick = tick + 1
942
+
943
+ val _ = pool.blockerThreads.put(this , java.lang.Boolean .TRUE )
944
+
945
+ if (pool.transferStateQueue.offer(transferState)) {
946
+ // If successful, a waiting thread will pick it up
947
+ // Register this thread in the blockerThreads map
948
+
948
949
} else {
949
950
// Spawn a new `WorkerThread`, a literal clone of this one. It is safe to
950
951
// transfer ownership of the local queue and the parked signal to the new
@@ -969,7 +970,7 @@ private[effect] final class WorkerThread[P <: AnyRef](
969
970
system,
970
971
_poller,
971
972
metrics,
972
- transferState ,
973
+ new WorkerThread . TransferState ,
973
974
pool)
974
975
// Make sure the clone gets our old name:
975
976
val clonePrefix = pool.threadPrefix
@@ -1010,6 +1011,8 @@ private[effect] final class WorkerThread[P <: AnyRef](
1010
1011
setName(s " $prefix- ${_index}" )
1011
1012
1012
1013
blocking = false
1014
+
1015
+ pool.replaceWorker(newIdx, this )
1013
1016
}
1014
1017
1015
1018
/**
0 commit comments