I think the gist of your solution is not so bad, but you can make your actor behave more like a state-machine by using context.become
:
class GaurdedIOActor extends Actor with Stash with AsyncIO {
import GuardedIOActor._
def receive = notReading
def notReading: Receive = {
case Read(offset, count) => {
val caller = sender
Read(offset,count).onSuccess({
case data => {
self ! ReadCompleted()
caller ! ReadResult(data)
}
})
context.become(reading)
}
}
def reading: Receive = {
case r: Read => stash()
case ReadCompleted() => {
context.become(notReading)
unstashAll()
}
}
}
Now your actor has two well-defined states and there's no need for the var