in util-core/src/main/scala/com/twitter/util/Promise.scala [503:542]
@inline private[this] def cas(oldState: Any, newState: Any): Boolean =
unsafe.compareAndSwapObject(this, stateOff, oldState, newState)
/**
* (Re)sets the interrupt handler. There is only
* one active interrupt handler.
*
* @param f the new interrupt handler
*/
final def setInterruptHandler(f: PartialFunction[Throwable, Unit]): Unit =
setInterruptHandler0(f, WaitQueue.empty)
@tailrec
private final def setInterruptHandler0(
f: PartialFunction[Throwable, Unit],
wq: WaitQueue[A]
): Unit =
state match {
case s: Transforming[A] =>
if (!cas(s, new Interruptible(WaitQueue.merge(wq, s.waitq), f, Local.save())))
setInterruptHandler0(f, wq)
case waitq: WaitQueue[A] =>
if (!cas(waitq, new Interruptible(WaitQueue.merge(wq, waitq), f, Local.save())))
setInterruptHandler0(f, wq)
case t: Try[A] /* Done */ => wq.runInScheduler(t)
case s: Interruptible[A] =>
if (!cas(s, new Interruptible(WaitQueue.merge(wq, s.waitq), f, Local.save())))
setInterruptHandler0(f, wq)
case p: Promise[A] /* Linked */ => p.setInterruptHandler0(f, wq)
case s: Interrupted[A] =>
if ((wq ne WaitQueue.Empty) &&
!cas(s, new Interrupted(WaitQueue.merge(wq, s.waitq), s.signal)))
setInterruptHandler0(f, wq)
else f.applyOrElse(s.signal, Promise.AlwaysUnit)
}