Dimitri Fedorov
07/08/2019, 7:33 PMelement.call() {
service.run() {
element2.call() { ... }
}
}
there is 2 requirements:
1. every element or service is invoking callback on proper thread already
2. every call shouldn’t block its own thread, i.e. each callback should exit after invoking next element/service (i can’t use suspendCoroutine
because of that)
what is proper coroutine way to do that?streetsofboston
07/08/2019, 7:37 PM...
element.call() // suspends until it is done.
service.run() // suspends until it is done.
element2.call() // suspends until it is done
...
(i assume from your example that your callbacks don’t provide a result, just a callback for when stuff is done…)Dimitri Fedorov
07/08/2019, 7:37 PMstreetsofboston
07/08/2019, 7:38 PM...
val result = element.call() // suspends until it is done.
val runResut = service.run() // suspends until it is done.
val result2 = element2.call() // suspends until it is done
...
Dimitri Fedorov
07/08/2019, 7:39 PMstreetsofboston
07/08/2019, 7:39 PMDimitri Fedorov
07/08/2019, 7:40 PMstreetsofboston
07/08/2019, 7:43 PMsuspend fun Element.call_() = suspendCancelableCoroutine { cont -> call() { cont.resume(it } }
suspend fun Service.run_() = suspendCancelableCoroutine { cont -> run() { cont.resume(it) } }
...
scope.launch {
val result = element.call_() // suspends until it is done.
val runResut = service.run_() // suspends until it is done.
val result2 = element2.call_() // suspends until it is done
}
Just gave the suspend variations of your functions the same name with an extra _
.
None of your threads will block, not the calling ones, nor your callback-threads.Dimitri Fedorov
07/08/2019, 7:46 PMstreetsofboston
07/08/2019, 7:47 PMscope
, a dispatcher that has only one thread in its thread-poolscope.launch(mySingleThreadedDispatcher) { … }
Dimitri Fedorov
07/08/2019, 7:50 PMscope
here?streetsofboston
07/08/2019, 7:51 PMresult2
in the end.Dimitri Fedorov
07/08/2019, 8:01 PMstreetsofboston
07/08/2019, 8:10 PMelement.call()
be made?Dimitri Fedorov
07/08/2019, 8:23 PMZach Klippenstein (he/him) [MOD]
07/08/2019, 8:25 PMDispatchers.Unconfined
.
val scope = Dispatchers.Unconfined + parentJob
scope.launch {
// Invoked on calling thread.
val result = element.call_()
// Invoked on whatever thread invoked the first callback.
val runResult = service.run_()
// Invoked on whatever thread invoked the second callback.
val result2 = element2.call_()
// Calling function will resume on whatever thread invoked the third callback.
}
Dico
07/08/2019, 8:35 PMrunBlocking
?Dispatchers.Unconfined
does. If one function changes thread, it will stay on that thread when it returns.Zach Klippenstein (he/him) [MOD]
07/08/2019, 8:38 PMDico
07/08/2019, 8:39 PMUnconfined
.
val scope = CoroutineScope(Dispatchers.Unconfined)
scope.launch(start = CoroutineStart.UNDISPATCHED) {
... code here
}
streetsofboston
07/08/2019, 8:39 PMDimitri Fedorov
07/08/2019, 8:39 PMrunBlocking { launch(Dispatchers.Unconfined) {
will run on current thread but also will block itZach Klippenstein (he/him) [MOD]
07/08/2019, 8:39 PMstreetsofboston
07/08/2019, 8:41 PMlaunch
from the Main UI thread and using the Dispatchers.Main, because that is the same thread, since the Main UI thread is part of the pool of Dispatchers.Main.Dimitri Fedorov
07/08/2019, 8:43 PMCoroutineScope(Dispatchers.Unconfined).launch(start = CoroutineStart.UNDISPATCHED)
) works fineZach Klippenstein (he/him) [MOD]
07/08/2019, 8:43 PMCoroutineStart.UNDISPATCHED
is redundant with Unconfined
dispatcher.streetsofboston
07/08/2019, 8:44 PMrun
and call
) will never be called on another thread. That would make for a leaky abstraction. Also, if that is the case, why use callbacks at all?Dimitri Fedorov
07/08/2019, 8:44 PMZach Klippenstein (he/him) [MOD]
07/08/2019, 8:45 PMThen you have to assume that the callbacks (the lambdas ofNot if you don’t care which threads your code is running on – in this case, it sounds like the intention is for those callbacks to be invoked on different threads.andrun
) will never be called on another thread.call
streetsofboston
07/08/2019, 8:46 PMZach Klippenstein (he/him) [MOD]
07/08/2019, 8:47 PMevery element or service is invoking callback on proper thread already
Dimitri Fedorov
07/08/2019, 8:47 PMCoroutineScope(Dispatchers.Unconfined).launch
seems to work, thanks a lot guys!streetsofboston
07/08/2019, 8:51 PMDimitri Fedorov
07/08/2019, 8:52 PMstreetsofboston
07/08/2019, 8:54 PMDimitri Fedorov
07/08/2019, 8:55 PMgildor
07/09/2019, 1:22 AMi can’t suspend current thread@Dimitri Fedorov It’s impossible to suspend thread, you can only block thread. And suspend function should not block thread (if you have some blocking thread in suspend function, you should wrap it with withCotntext(IO/Default)
Dimitri Fedorov
07/09/2019, 7:50 AMgildor
07/09/2019, 7:50 AMDimitri Fedorov
07/09/2019, 7:54 AMgildor
07/09/2019, 7:55 AMevery call shouldn’t block its own thread, i.e. each callback should exit after invoking next element/service (i can’t usebecause of that)suspendCoroutine
Dimitri Fedorov
07/09/2019, 8:05 AMgildor
07/09/2019, 9:57 AMjust wasnt using them in proper contextWhat do you mean?
Dimitri Fedorov
07/09/2019, 10:25 AMCoroutineScope(Dispatchers.Unconfined).launch
, works as it shouldgildor
07/10/2019, 1:31 AM