actor, fixed thread pool, a channel with 2 listeni...
# coroutines
w
actor, fixed thread pool, a channel with 2 listening coroutines
a
Right, but if I have an actor I wouldn’t need a fixed thread pool. Also, the problem of knowing when the job is complete remains as well as being able to cancel a pending job.
g
Could you show a bit more context, which features do you need, how do you plan to use such API. Because there are different ways to limit concurrency that work better for different cases
Just to reference you can check this talk by Roman about limiting concurrency using worker pool pattern

https://youtu.be/a3agLJQ6vt8

(see part from 18:42)
👍 1
a
So the reason for it is a memory issue. Bitmaps are large and I don’t want too many in memory at the same time. Loading the full size bitmap is done on an IO dispatcher, then on a computation dispatcher I want to create a thumbnail and write it to disk. While all of this is happening I don’t want other bitmaps to be generated.
g
Looks that worker pool should work for this
a
Another example would be an HTTP client that don’t want to make more than 5 concurrent requests
w
g
More tricky with http request, because you probably want limit amount of request per host, and some clients has own way to manage concurrency (for example OkHttp has own dispatchers API that allows you configure concurrency)
a
It was more to illustrate the problem, regardless of a per host limit you probably want an overall limit too since your system will not work well with thousands of pending HTTP calls
g
I still think that manage this on http client level is better approach, as you said http call and socket is global system resource, so better manage it globally
a
Well again, regardless of where you implement the limit the problem exists. Somewhere you need to limit concurrency. I’m not building an HTTP client it is just another example that illustrates the problem of concurrency vs parallelism
g
But nothing prevents you from limiting concurrency on coroutines level
Like in Roman's talk
My point that in each particular case you should consider what is the best approach. For example in case of bitmap processing (which is probably not cancellable blocking operation) I would just use fixed thread pool: easy and safe solution
a
Well in my case it isn’t just a blocking operation. The reading and writing of files happens async and won’t block the pool. I don’t want to start reading a new file until i’ve completed the work on the previous
g
Now it's not so good, because you have to create pool ourselves with new threads, but when we get API that allow us get new dispatcher using existing IO threads, it would be really efficient
Even with non blocking read and write I don't see problem with this approach, less efficient (you use more threads than could), but still work. Otherwise just use worker pool for that
a
The problem is that you can read more bitmap concurrently than there are threads in the pool since the read operation is non blocking
g
You can make operation blocking, sounds kinda bad of course, but probably reading and writing are just much faster than actual processing. I just want to say that it is easy solution for mostly blocking job
a
Yeah, I could use for example
runBlocking
inside my
withContext
but that feels like an anti pattern
I think an actor would be the best choice, and just deal with the problems of cancellation and completion in some other way
g
Keep in mind that you cannot cancel blocking operation anyway And in any case you need some solution for cancellation of elements in queue and you have this problem with any solution: actor/channel, thread pool or any other queue
Just curious how read and write are implemented to be non-blocking, Java NIO?
a
The actual reading is not async, it’s just being performed on another dispatcher
g
Sounds that it just waste of threads and unnecessary context switch, why not just use blocking reading on the same thread where you do processing, also Jo problem with concurrency limitation
a
The reading is done by a different subsystem that makes sure that multiple people doesn’t read the same files individually
g
I see
a
I think worker pools are the answer, but’s it’s tricky to get right. If it was done in pure java i would have used a countdown latch for this but unfortunately coroutines doesn’t have a non blocking latch
g
Not so tricky, just a channel that reads simultaneously by multiple coroutines. But complicated chain of such workers may be tricky, it's true
a
My problem is quite similar to the example in the video that you linked (which is great BTW). My problem is that I want a shared worker pool and when people send something to the channel I want to merge duplicate requests (multiple callers want the same thumbnail) as well as wait for a response