Last active
December 17, 2015 22:38
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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