Separate generally useful Finatra utilities from Finatra example.

That's such a great question that it deserves a blog post. I have been anticipating it, and I haven't had the time to get around to writing said post. Sigh.

That Async class began life much more closely married to java.nio.channels.CompletionHandler.  It has slowly evolved into what you see now. I saw its relationship to Future and considered switching, but I've kept it around because it's simpler than a Future, it works well with Fiber, and the related Scheduler has a really useful stub.

1. It's simpler. Take a look at the Scala Future implementation. You'll see it confounds notions of channels and uses synchronized.  The Async and Callback classes leave message queuing for something else.

1. Fiber is nice.

    A Fiber is like an actor, but a bit easier to use. For example:

        class Counter (implicit scheduler: Scheduler) {
          private val fiber = new Fiber
          private var x = 0
          def inc(): Unit = fiber.execute (x = x+1)
          def get(): Async [Int] = fiber.supply (x)
        }

    In a comparable Actor, you'd need to explicitly define message classes for Inc, Get and GetResult. The same classes are above, but they are hidden as anonymous classes.

1. The Scheduler has a useful stub.

    The scheduler has a stub that is single threaded, and uses a PRNG to pick the next task to run. You can build a system of interacting Fibers, construct some test cases, and then run the tests using the stub. If you seed the stub scheduler with the same value each run, it will run interleaved tasks in the same order. Or you can seed it with different values to test different ways of interleaving tasks. This doesn't catch all multithreading bugs, but it sure does catch a lot of mistakes. And when it does catch a problem, you can use the seed that produced the error to rerun the exact same interleaving, over and over while you try to debug the problem.

I have extended the notion of the stub scheduler to include a stub network that can reorder and drop messages, and stub hosts that can crash. This collection of stubs has been invaluable in testing that the storage system supports atomic writes and snapshot reads while machines are crashing and rebooting, while the network is flakey, and while replicas are rebalancing (to accommodate storage nodes being added or removed from the cluster). To switch Treode's Async to Scala's Future would mean also rewriting all that useful testing framework.