Luis Munoz
08/01/2019, 8:25 PMgroostav
08/01/2019, 8:26 PMupdate()Luis Munoz
08/01/2019, 8:26 PMLuis Munoz
08/01/2019, 8:27 PMLuis Munoz
08/01/2019, 8:27 PMDominaezzz
08/01/2019, 8:27 PMMutex or AtomicInt .groostav
08/01/2019, 8:28 PMclass Example : CoroutineScope {
//extending coroutine scope doesnt get you anything implicitly. It does make `launch()` and `async` et all easier to use
val mutex = Mutex()
suspend fun update() {
mutex.withLock {
count++
}
}
}Luis Munoz
08/01/2019, 8:28 PMgroostav
08/01/2019, 8:28 PMDispatchers.Main, Dispatchers.JavaFx, etc)
suspend fun update() = withContext(this.coroutineContext){
count++
}Luis Munoz
08/01/2019, 8:29 PMgroostav
08/01/2019, 8:30 PMLuis Munoz
08/01/2019, 8:31 PMDominaezzz
08/01/2019, 8:31 PMgroostav
08/01/2019, 8:31 PMDispatchers.Default will give you highly parallel behaviour by default. If thats part of your context you will find it running in parallel on many different threads.
I will say that koltin coroutines typically offer sqeuential concurrent behaviour by default. This is easier to leverage if you avoid state machiens (eg update()) instead favouring channels.groostav
08/01/2019, 8:34 PMLuis Munoz
08/01/2019, 8:34 PMgroostav
08/01/2019, 8:35 PMmutex.withLock { mutex.withLock {}} will deadlockLuis Munoz
08/01/2019, 8:38 PMgroostav
08/01/2019, 8:40 PMExecutors.newSingelThreadedExecutor().asCoroutineDispatcher() in your scope's context and then withContext--ing every entry point will give you single-threaded concurrency, which might be helpful.Luis Munoz
08/01/2019, 8:43 PMLuis Munoz
08/01/2019, 8:44 PMDominaezzz
08/01/2019, 8:45 PMDominaezzz
08/01/2019, 8:45 PMDominaezzz
08/01/2019, 8:45 PMLuis Munoz
08/01/2019, 8:49 PMgroostav
08/01/2019, 8:50 PMDominaezzz
08/01/2019, 8:51 PMLuis Munoz
08/01/2019, 8:57 PMDominaezzz
08/01/2019, 8:59 PMgroostav
08/01/2019, 11:32 PMExecutors, such that rather than have Executors.newSingleThreadedExecutor and Executors.forkJoinPool you would have Executors.make(context = SingleThreaded). You can absolutely take a coroutine context and re-use it by doing
val context = EmptyCoroutineContext + MySpecialContext
GlobalScope.launch(context) { /* job1 */ }
GlobalScope.launch(context) { /* job2 */ }
In this way, both job1 and job2 have the same context.
The purpose of scope (as opposed to context) is mostly to try and employ a parent-child relationship to try and keep management a little easier and error states a little cleaner.Luis Munoz
08/07/2019, 7:52 PMLuis Munoz
08/07/2019, 7:52 PMLuis Munoz
08/07/2019, 7:52 PMDominaezzz
08/07/2019, 8:27 PMDominaezzz
08/07/2019, 8:29 PMgroostav
08/07/2019, 11:58 PMlaunch does indeed give you a new coroutine context with a new (parent) job in it. Context is a key value store. The implementation of parent-child'ing in jobs relies on a mutable Job implementation. To my knowledge all other coroutine context elements are either stateless or immutable.groostav
08/08/2019, 12:04 AMsuspend fun method there is nothing in a coroutine's context that will help you directly. You can get single-threaded behaviour by changing Dispatchers. You can use mutex to acquire a lock --you could even put it in your coroutine context to make it a reentrant lock.