Skip to content

Instantly share code, notes, and snippets.

@Narigo
Created August 29, 2012 22:57
Show Gist options
  • Save Narigo/3519989 to your computer and use it in GitHub Desktop.
Save Narigo/3519989 to your computer and use it in GitHub Desktop.
Scala ways to handle event based stuff?
package com.campudus.scalasnippets
import actors.Actor._
import java.util.concurrent.atomic.AtomicInteger
import scala.annotation.tailrec
object SomeAsyncTests {
def asyncFunction(i: Int)(doWhenDone: => Unit) = actor {
println("doing stuff " + i)
Thread.sleep(1)
doWhenDone
}
// The type signatures could probably be optimized somehow...
def asyncToSync(cleanup: => Unit)(stuffToDo: (((=> Unit) => Unit) => Unit) => Unit) = {
val counter = new AtomicInteger(0)
var done = false
def synchronizer(fn: (=> Unit) => Unit) = {
// Count up, to remember to wait for another function to finish.
counter.incrementAndGet()
// Invoke the function we are waiting for
fn({
// When the function finishes, the counter needs to know it's done.
// If the whole block of functions is ready, it's time for the cleanup.
if (counter.decrementAndGet == 0 && done) {
cleanup
}
})
}
stuffToDo(synchronizer)
done = true
// If all functions finished already, clean up!
if (counter.get == 0) {
cleanup
}
}
def main(args: Array[String]): Unit = {
val i = new AtomicInteger(0)
val numberOfAsyncFuns = 200
def cleanup(s: String) = { println("cleanup " + s) }
// A) async
// The "usual" event-based way, call a method after work was done
// Con: You need to keep track of the number of async-functions you invoke
val counter = new AtomicInteger(numberOfAsyncFuns)
for (x <- 1 to numberOfAsyncFuns) {
val funNumber = i.incrementAndGet
println("starting " + funNumber + " in A)")
asyncFunction(funNumber) {
if (counter.decrementAndGet == 0) {
cleanup("A")
}
}
}
// B) async
// Another way, trying to keep track of the functions for you
// Con: You need to wrap every function call in a "sync()" block
asyncToSync(cleanup("B")) {
sync =>
for (x <- 1 to numberOfAsyncFuns) {
val funNumber = i.incrementAndGet
println("starting " + funNumber + " in B)")
sync(asyncFunction(funNumber))
}
}
// are there other/better ways of doing that?
// C) sync way of chaining functions
asyncFunction(i.incrementAndGet) {
asyncFunction(i.incrementAndGet) {
asyncFunction(i.incrementAndGet) {
asyncFunction(i.incrementAndGet) {
asyncFunction(i.incrementAndGet) {
cleanup("C")
}
}
}
}
}
// D) like C
def afterEachOther(c: Int): Unit = c match {
case 1 => asyncFunction(i.incrementAndGet)(cleanup("D"))
case x => asyncFunction(i.incrementAndGet)(afterEachOther(c - 1))
}
afterEachOther(numberOfAsyncFuns)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment