Skip to content

Instantly share code, notes, and snippets.

@ellbur
Last active December 17, 2015 22:38
Show Gist options
  • Select an option

  • Save ellbur/5682980 to your computer and use it in GitHub Desktop.

Select an option

Save ellbur/5682980 to your computer and use it in GitHub Desktop.
Passing continuations in an Actor to offload a long-running, multi-step computation without making a state machine.
import javax.swing._
import java.awt.{List => _, _}
import scala.util.Random
import scala.actors._
import Actor._
import java.awt.event._
object ActorContinuationTest extends App {
// The GUI
def later(f: => Unit) {
SwingUtilities.invokeLater(new Runnable {
def run() { f }
})
}
val startButton = new JButton("Start")
startButton.addActionListener(new ActionListener {
def actionPerformed(p1: ActionEvent) { leonardo ! Start }
})
val stopButton = new JButton("Stop")
stopButton.addActionListener(new ActionListener {
def actionPerformed(p1: ActionEvent) { leonardo ! Stop }
})
def setRunning(running: Boolean) {
startButton.setEnabled(!running)
stopButton.setEnabled(running)
}
val resultLabel = new JLabel(" ")
val win = new JFrame("Actor Continuation Demo")
win.setLayout(new FlowLayout())
win.add(startButton)
win.add(stopButton)
win.add(resultLabel)
win.pack()
win.setVisible(true)
def clearMeasurements() { resultLabel.setText("???") }
def giveResult(x: Double) { resultLabel.setText(f"$x%.3f") }
// The offloaded computation
case object Start
case object Stop
val leonardo = actor {
def stop() {
later(setRunning(false))
react {
case Stop => stop()
case Start => run()
}
}
def then(cc: => Unit) {
reactWithin(1) {
case TIMEOUT => cc
case Stop => stop()
case Start => run()
}
}
def run() {
later(setRunning(true))
later(clearMeasurements())
readXs() { xmean =>
later(giveResult(xmean))
}
}
def readXs()(cc: Double => Unit) {
def iter(n: Int, pts: List[Double]) {
then {
if (n <= 0)
cc(pts.sum / pts.length)
else
iter(n-1, readX() :: pts)
}
}
iter(5, Nil)
}
loop {
stop()
}
}
// The device
def connectToDevice() {
println("Connect to device")
Thread.sleep(1000)
}
def readX() = {
println("Read X")
Thread.sleep(1000)
Random.nextGaussian()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment