@@ -12,10 +12,17 @@ import lattice.{ DefaultKey, Key, Updater }
1212import org .opalj .graphs ._
1313
1414import scala .collection .immutable .Queue
15+ import scala .util .{ Success , Try }
1516
1617/* Need to have reference equality for CAS.
18+ *
19+ * quiescenceCellHandlers use NEXTCallbackRunnable, because (a) pool might reach quiescence
20+ * repeatedly and (b) cell might not be completed, when quiescence is reached.
1721 */
18- private class PoolState (val handlers : List [() => Unit ] = List (), val submittedTasks : Int = 0 ) {
22+ private class PoolState (
23+ val quiescenceHandlers : List [() => Unit ] = List (),
24+ val quiescenceCellHandlers : List [NextCallbackRunnable [_, _]] = List (),
25+ val submittedTasks : Int = 0 ) {
1926 def isQuiescent (): Boolean =
2027 submittedTasks == 0
2128}
@@ -63,13 +70,27 @@ class HandlerPool(parallelism: Int = 8, unhandledExceptionHandler: Throwable =>
6370 if (state.isQuiescent) {
6471 execute(new Runnable { def run (): Unit = handler() })
6572 } else {
66- val newState = new PoolState (handler :: state.handlers , state.submittedTasks)
73+ val newState = new PoolState (handler :: state.quiescenceHandlers, state.quiescenceCellHandlers , state.submittedTasks)
6774 val success = poolState.compareAndSet(state, newState)
6875 if (! success)
6976 onQuiescent(handler)
7077 }
7178 }
7279
80+ @ tailrec
81+ final def onQuiescent [K <: Key [V ], V ](cell : Cell [K , V ])(handler : Try [V ] => Unit ): Unit = {
82+ val state = poolState.get()
83+ if (state.isQuiescent) {
84+ execute(new Runnable { def run (): Unit = handler(Success (cell.getResult())) })
85+ } else {
86+ val runnable = new NextConcurrentCallbackRunnable (this , null , cell, handler)
87+ val newState = new PoolState (state.quiescenceHandlers, runnable :: state.quiescenceCellHandlers, state.submittedTasks)
88+ val success = poolState.compareAndSet(state, newState)
89+ if (! success)
90+ onQuiescent(cell)(handler)
91+ }
92+ }
93+
7394 /**
7495 * Register a cell with this HandlerPool.
7596 *
@@ -265,7 +286,7 @@ class HandlerPool(parallelism: Int = 8, unhandledExceptionHandler: Throwable =>
265286 var submitSuccess = false
266287 while (! submitSuccess) {
267288 val state = poolState.get()
268- val newState = new PoolState (state.handlers , state.submittedTasks + 1 )
289+ val newState = new PoolState (state.quiescenceHandlers, state.quiescenceCellHandlers , state.submittedTasks + 1 )
269290 submitSuccess = poolState.compareAndSet(state, newState)
270291 }
271292 }
@@ -281,10 +302,10 @@ class HandlerPool(parallelism: Int = 8, unhandledExceptionHandler: Throwable =>
281302 val state = poolState.get()
282303 if (state.submittedTasks > i) {
283304 handlersToRun = None
284- val newState = new PoolState (state.handlers , state.submittedTasks - i)
305+ val newState = new PoolState (state.quiescenceHandlers, state.quiescenceCellHandlers , state.submittedTasks - i)
285306 success = poolState.compareAndSet(state, newState)
286307 } else if (state.submittedTasks == 1 ) {
287- handlersToRun = Some (state.handlers )
308+ handlersToRun = Some (state.quiescenceHandlers )
288309 val newState = new PoolState ()
289310 success = poolState.compareAndSet(state, newState)
290311 } else {
0 commit comments