I have been working with C#’s TPL for a while now, and coming back to Java once in a while for Android or some web stuff always makes me hate every bit of it. Not the JVM part (In my opinion JVM is way better than CLR), but the writing part of it (not to say I have problems with C# here and there). The way threads and callbacks are implemented, and functions were not first class citizen until recently. Although Java 8 brings a lot to table, there are still problems that need to be addressed, one of them is Futures (or async/await or promises or deferred) and I strongly feel Kotlin even during it’s infancy is pulling off more than expected. In this blog post I am going to reason about why you need a better async programming model, a little bit of my history with Kotlin, and how Kotlin brings interesting stuff to table.
All of this is my personal opinion, and in no way says one promoting one technology over the other. I however will show you what has been done wrong in the past and how various technologies are inspiring from each other and adding something new to the paradigm.
I am going to build my case using Android a typical developers nightmare. Quoting Swing or JavaFX might sound less relevant to most of developers, as a bigger audience out there is working on Android these days. If you have tried writing an Android application, doing back and forth transitions between main thread (aka UI thread) and background threads you know where am I gonna go with this. Just as a refresher I will quote this tutorial; you can find plethora of such tutorials and techniques advocated on StackOverflow and blogs. In a typical scenario for any kind of IO or compute intensive process you will launch a background thread, after completing you some how invoke a callback or method that ultimately runs rest of code on UI aka runOnUiThread
.
But wait, there are libraries to write better code for such scenarios, libraries like RxJava, Otto etc. “Why not use them?” one may ask. Well if you have been to the dreaded land of UWP (Universal Windows Platform) and developed an application in C#, you might have tasted what I refer to as simplicity. The Task Parallel Library makes it a breeze to spin of large number of tasks, and controlling which one runs on what thread, or on what context will the execution resumes. There is obviously a learning curve, but once you get hold of it; you would mentally replace threads with tasks almost everywhere in your daily routine. Although the Android libraries advocate really good patterns but none compares to simplicity of invoking something like a function that runs on a background thread and return values to you like a normal function does. No callbacks, no event tracing, no stream of events, no tracking nothing. Dead simple function like invocations! This not only simplifies writing code but also makes debugging an easier job. Rather than guessing and searching annotations in code; you know where is the invoked code located, and how it resumes once invocation is completed.
Let me put it this way, what would you prefer? A simple var user = await getUserInfo()
or (wait I have to use Otto and use multiple lines to show part of the problem):
// Somewhere in codebus = new Bus(ThreadEnforcer.MAIN);bus.register(this);...
// Somewhere else in code@Subscribepublic void onUserInfo(User u) { Toast.makeText(this, this.getUserMessage(u), Toast.LENGTH_LONG).show();} ...
// In a galaxy far far away
// carry the stupid bus around
this.`bus.post(user);`
}
...
}
This alone should be good enough to convince you about problem in your code. If it’s hard and scattered to explain in code, then it’s hard to debug. I can quote a similar example with RxJava.
Again don’t get me wrong, I am not implying in any possible way Otto or RxJava are stupid duck tapes, they totally have valid usages. One I can think of on top of my head right now is providing an update on UI when there is a push event from server. But it doesn't mean it’s perfect for every scenario, right? Another option could be Bolt Framework. Which inspires it’s API almost directly from C# TPL. While it does provide you with continueWith
, onSuccess
, or onSuccessTask
etc. there is still the tax of callbacks, and some Continuation
initialization.
Android’s workflow was just as an example, even at language level having asynchronous programming constructs, and then being able to multiplex it over a thread pool is critical. No matter if it’s HTTP server, or a DB engine; asynchronous paradigm has proved it’s ground over time.
While Java 8 already has support for CompletableFutures the luxury of async/await gives it a certain intuitiveness that we all are familiar with. There is a reason why callback hells like Node.js is also moving towards async/await support, Python 3.6 did a really neat implementation recently, and C# has TPL.
I tried Kotlin once or twice before trying to build an Android app. Kotlin was just getting started in those days. While I did enjoyed the really small runtime, interoperability, concise syntax, and cleaner less ceremonial approach with great comprehension. To be Android specific the ability to pass callbacks like fun onClick(listener: () -> Unit)
and hook them up without parenthesis like a function body view.onClick { ... }
. It also allowed simpler data classes, function extensions, and a extensive list of libraries already supporting it. Happy but not satisfied, I was still looking for some sort of async/await support, and went back to my routine work using Kotlin where ever I can. If you are Android enthusiast and want to read more on why you should use Kotlin, there are may good reads out there.
With recent announcement of Kotlin 1.1 seems like my wish is almost fulfilled. Although the feature is experimental yet, but I don’t see it too far from being production ready, since I am able to fully express all the scenarios that I have seen practically during my app development experience. Just to try it out after I heard about the new release, I rewrote a service that Geolocates an IP and using coroutines.
I won’t go in tutorial mode about coroutines here as you can go find every thing you need on official documentation. For Android people there is a really good Kotlin coroutine article and few more libraries already supporting Kotlin 1.1 coroutines. While working on the server code I observed few things about coroutines that I feel go beyond the usual async/await implementation (even beyond what C# does). They are not only a syntactic cleanup to what you might have been doing, but they also provide some powerful ways to express your code for complex scenarios. Lets go through few of them:
While C# TPL gives you the fundamental blocks for Tasks and inspires many of modern async implementations; the inter task communication has not been addressed really well. One might say you use BufferBlock
or use techniques described here. But like Golang, or Erlang where channels or mailboxes are first class citizens it’s much cleaner to express communication. Kotlin coroutines takes a page from above and comes with built-in channel support (documentation). This lets you implement complicated patterns like pipelines, fan-out, or fan-in etc. Couple channels with the select expression and you can write complex dispatchers like:
suspend fun chatMessageProcessor(users: ReceiveChannel<IMessage>, system: ReceiveChannel<IMessage>, timeout: ReceiveChannel<IMessage>) {select<Unit> {users.onReceive { value -> ... }system.onReceive { value -> ... }timeout.onReceive { value -> ... }}}
While this will sound familiar to many Golang folks, in JVM land it’s a really neat way to wait for one of multiple events and then act accordingly (I can already see some Akka fans pulling out their hair). This can let you spin off some coroutines that encapsulate some state and acts on them on some messages from environment. For example wait for a message from UI and then do updates to DB, or maybe make API calls to a server. Another example might be publishing chat messages to other coroutines that pushes a chat message to other users in same chat-room. Does this sound familiar? We are moving closer to Actors.
Actors are objects which encapsulate state and behavior, they communicate exclusively by exchanging messages which are placed into the recipient’s mailbox. — Akka
Kotlin coroutines library comes with basic actors support, and awesome part is it’s syntactically clean as well; you don’t have to implement an interface, or define required methods for ceremonial purposes. It’s just like a go routine or an Erlang process, a simple function. Here is how simple it looks like:
fun messageDeliveryActor() = actor<ChatMessage>(CommonPool) {// Do your stuff here...}
Like any other async
or run
it requires a context and that’s about it! Do keep in mind there are already mature libraries for Java that provide actor support. I am not undermining any of them!
So while writing the server I came across the typical problem of existing packages not supporting or utilizing the async APIs (No Java NIO, no netty, no nothing). The DatabaseReader
of Maxmind GeoIP2 library uses the File
object; Now calling any operation that reads from File would have blocked the thread in my thread pool. While one solution is to do a an async implementation myself, that is not always feasible. Call me a slacker the solution that I used was to have a thread pool for these kind of blocking operations, and have my IO coroutine bound only to that context. That way I will never block my request handling threads. Here is structure of what internals of my lookup class may look like:
findContext = newFixedThreadPoolContext(4)
suspend private fun find(ip: String): CityInfo? = run(findContext) {// Do the blocking thread blocking lookups here}
Invoking this subroutine from my request is really transparent. In my case I am using jooby
and it supports async via Deferred
. So my code for invoking find looks like this:
**fun** getGeoInfo()= Deferred { req, def ->
launch (CommonPool) {
...
**val** ip = req.param("ip").value() ?: req.ip()
// lookupEngine.find won't use CommonPool
**val** info = lookupEngine.find(ip)
...
}
}
See the seamless transition when you invoke find(ip)
. Without exposing knowledge of using a different thread pool, I invoked a coroutine on a different context and will be getting results back without any shenanigans. Now this is possible due to both Kotlin’s syntax and coroutine implementation and shows how they go hand in hand to provide such a transparent context switching. This not only abstracts the knowledge away but takes away the coding cost that I might have to pay otherwise. Complete code of the server is available here.
I think I will stop here. I would let you guys try it yourself and build your own opinion. One might say Scala already has the async/await support! What is so exciting or different in Kotlin? I have honestly tried Scala many times, but was always overwhelmed by the syntax (I don’t know why, there are so many ways to do so many things). I really want to go to Scala town where I can mix-n-match functional, and object oriented style. But for now I am happy to see an emerging syntactically decent and clean coroutine implementation. Kotlin might be young but it’s surprisingly pleasant, stable, has an awesome community and bringing the always wanted support of coroutines to JVM.