This library provides an abstraction layer over the target-specific concurrency APIs, namely:
Thread
Queue
Tls
Mutex
Being largely based on abstracts, it avoids allocation of wrapper objects, although in a multi-threaded environment that will probably hardly matter on a performance level. But if you compare java.vm.Thread and tink.concurrent.Thread, you will see that it also decreases complexity.
This library runs on all platforms out of the box, like so:
Thread
is implemented as dummyQueue
is implemented as aList
Tls
is implemented as atink.core.Ref
Mutex
is implemented with mere noops
There's exactly two things that will not compile without -D concurrent
- creation of new threads (with
new Thread
) - blocking reads from a
Queue
(withawait
)
In those cases the library will actually tell you explicitly that concurrent
is required (instead of the compiler complaining that a class or method is not found).
Support for -D concurrent
exists on neko, java and cpp. On all other targets you will get compiler errors.
For full portability, you will have to work around differences in the API that come from the concurrent
flag. There are so many approaches, that this library cannot prescribe you how to go about it. This library is in fact not really intended for direct use, but rather with tink_lang and/or tink_runloop.
Ensuring code to run both with and without -D concurrent
is a worthwhile endeavor.
- In some cases you execute code in an environment where you cannot create threads, because either the OS itself or other constraints don't allow it. In those cases all abstractions are replaced by cheap non-concurrent implementations, so there will be no performance penalty.
- It is also useful for debugging purposes.
This library omits reading and writing messages to threads directly. Surprisingly just using a Queue
showed equal performance, and was thus chosen as the prefered way to pass messages, to increase type safety and keep the API lean.
The Queue
API itself is slightly different from the corresponding Deque
API. This concerns dissecting pop
into two calls, because they are then more easily mapped to the type system and allow for more intelligible compiler errors.