How I Learned to Stop Worrying and Handle Concurrency.

Fumiya Chiba
Tombo Blog
Published in
2 min readFeb 14, 2017

Concurrency is an unavoidable subject when creating a GUI application. In particular, heavy processes such as network communication and file I/O are generally handled by a separate thread from the GUI thread. Such threads are created in two ways:

  1. The application explicitly creates threads.
  2. The application implicitly creates threads via an API and asynchronously receives results with a callback function.

While you can use either style in iOS, you can only use the latter for Emscripten purposes. This is because the browser’s Javascript doesn’t support threading.

Technically, pthread has been implemented experimentally in Javascript. But it depends on SharedArrayBuffer, which in turn is only enabled in Firefox Nightly. So in any case, it’s not widely available yet.

(We’ve heard that it’s under development for Chrome though, and we’re eagerly awaiting for support by other browser vendors as well!)

With no pthread support widely available in browsers, we had to come up with workarounds to handle iOS concurrency in Javascript.

Case 1: Asynchronous Calls

Let’s first consider a simple asynchronous call.

Grand Central Dispatch (GCD), a framework for handling the queue, is most frequently used on iOS for asynchronous processes. GCD is implemented in the libdispatch library. But since it uses pthread and the iOS kernel API, it can’t be used as is.

To get around this, we wrote emulation code for key functions such as dispatch_async and dispatch_source (timer). The emulation itself is simple: we delegate queue processing to JavaScript’s event loop using setTimout().

Case 2: Explicit Calls

Next, let’s consider explicit calls.

Is it not possible to convert code that explicitly creates new threads? Have no fear! When we looked at the source code of several iOS applications, we found that most explicitly created threads fell into one of these three categories.

  1. When the task is completed, it terminates as is without notifying the result to other threads.
  2. When the task is completed, it notifies the main thread with a callback.
  3. It repeats some process using NSRunLoop (process some sort of task queue).

In each of these cases, NSThread is typically used.

So we reimplemented NSThread using GCD. Now, as long as these threads are called in an orderly fashion using NSThread, they are automatically processed using the queue without any code modifications.

This does mean that processes that would have been handled in the background are now executed in the main thread (postponed by setTimeout()), so there are times when the app lags a bit.

But if the task is network communication or file I/O, it won’t be a big problem. Network communication uses XHR, so Javascript will execute it in the background. Emscripten processes File I/O on-memory, so it is much faster than the actual on-device I/O.

Conclusion

We can now support iOS concurrency in our converted web applications. But we’re looking forward to the day when we can throw out all this code and use pthreads instead!

--

--