BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage News Fresh Async with Kotlin: Roman Elizarov Presents at QCon SF

Fresh Async with Kotlin: Roman Elizarov Presents at QCon SF

Bookmarks

Roman Elizarov, team lead for Kotlin libraries at JetBrains, presented "Fresh Async with Kotlin" at QCon San Francisco. During his presentation, Elizarov demonstrated how Kotlin addresses the difficulties faced in writing asynchronous code in languages such as Java, C# and Javascript. Asynchronous code in Kotlin looks very much like the normal synchronous code that most developers are used to writing in languages such as Java.

Traditionally, applications did a lot of direct computation and processing but many modern applications call services such as REST APIs or microservices. This architectural style typically involves waiting for the result to come back.

Image 1

In the code shown above, developer calls requestToken() service and waits for the token, then passes the token to createPost() service and waits for the created post, and finally calls processPost() service to render the post.

One simple way to implement this is with threads. However, whilst it is usually OK to use threads for simple cases like the three step code above, relying heavily on threads may not be feasible for complex applications involving numerous service calls. Each thread has a memory and scheduling overhead and so even modern machines can only have a limited number of threads live at once.

Callbacks provide an alternative to threads, especially in single threaded environments using Javascript. Code using callbacks tend to have too much code nesting called "callback hell" as shown in the following example.

Image 2

This nested code problem gets worse with complex code - nested code with callbacks is inherently hard to read and difficult to debug.

In recent years, Futures/Promises/Rx, which are all ways to implement the same general idea in different languages, have become known as a good alternative to address the issue of callback hell.

Code written using Futures/Promises is easier to read and understand than callback hell. This approach also has built in exception handling mechanism, which makes it  easier to debug the code.

However, there are still potential problems with the use of Futures/Promises. For example, dealing with multiple combinator methods on the Future container object. The above code uses two combinators .thenCompose and .thenAccept. Combinators may have different names in different languages, also a developer has to remember combinators for code branching, loops, etc.

Kotlin coroutines aim to help mitigate the issues a developer face with Futures/Promises. Coroutines allow the developer to write the code with natural signatures that  developers use when writing synchronous code. Coroutines use the suspend keyword at the beginning of the coroutine definition to indicate asynchronous operation.

Image 4

The disadvantage of this approach, though, is that it is difficult to tell which of the service calls are asynchronous. In the above code for example, there is no way to tell that requestToken() and createPost() calls are asynchronous. The IDE can help here by showing suspension point markers in the gutter.

By using coroutines, a developer now writes regular loops, regular exception handling, and regular higher order functions such as forEach, let, apply, repeat, filter, map, use, etc. A developer can also create custom higher order functions with the normal coding style used in synchronous coding.

Under the hood, when Kotlin compiler sees suspend keyword, it adds an invisible Continuation parameter to the function call at JVM bytecode level. This Continuation parameter is basically a callback.

Image 5

When Kotlin sees a sequence of suspension points, it compiles them to a state machine stores the suspension in the state machine.

Image 6

Developers are encouraged to explore the Kotlin coroutine library for all the coroutines available in Kotlin to support asynchronous programming. These libraries are still evolving and are experimental at present. However, they include integrations with other asynchronous programming approaches, such as CompleteableFuture, RxJava and Reactive Streams. They also provide hooks to allow Kotlin to integrate with single-threaded UI frameworks, including Android and JavaFX.

Rate this Article

Adoption
Style

BT