Skip to content

Instantly share code, notes, and snippets.

@pchiusano
Created January 30, 2014 22:32
Show Gist options
  • Select an option

  • Save pchiusano/8721475 to your computer and use it in GitHub Desktop.

Select an option

Save pchiusano/8721475 to your computer and use it in GitHub Desktop.
Killing a running `Process` asynchronously
import scala.concurrent.duration._
import scalaz.stream.{async, Process, wye}
val p1 = Process.awakeEvery(3 seconds)
val alive = async.signal[Unit]; alive.set(()).run
// this could be a generic combinator - zip takes the 'shorter' stream, so
// when 'alive' cuts out, that will kill off `p1`
val killableP1 = alive.continuous.zip(p1).map(_._2)
// in thread 1
killableP1.flatMap { _ => /* do some stuff */ }
.run.runAsync { e: (Throwable \/ Unit) => /* Handle yer async errors */ }
// meanwhile, in thread 2
doSomeStuff()
doSomeMoreStuff()
alive.close.run // this will kill `p1` when it wakes up next
/* If you want to kill `p1` _asynchronously_, ASAP, not just the next time it wakes up,
you can use the `interrupt` combinator. It looks a little different, but idea
is similar.
*/
val interrupted = async.signal[Boolean]; interrupted.set(false).run
val killableP1 = interrupted.wye(p1)(wye.interrupt)
// Then, to kill `p1` as quickly as possible from thread 2
interrupt.set(true).run
// fyi, here is the definition of `wye.interrupt`:
/**
* Let through the right branch as long as the left branch is `false`,
* listening asynchronously for the left branch to become `true`.
* This halts as soon as the right branch halts.
*/
def interrupt[I]: Wye[Boolean, I, I] = {
def go[I]: Wye[Boolean, I, I] = awaitBoth[Boolean,I].flatMap {
case ReceiveR(None) => halt
case ReceiveR(i) => emit(i) ++ go
case ReceiveL(kill) => if (kill) halt else go
case HaltOne(e) => Halt(e)
}
go
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment