Apart from using a Channel/Actor, is there any eas...
# coroutines
d
Apart from using a Channel/Actor, is there any easy way to implement an
ConcurrentHashMap
with coroutines that suspends the current Coroutine instead of blocking the thread? Sometimes retrieval of missing values can take time...
g
what you don’t want to use Actor/Channel? Which is good solution for this problem (especially if you wrap them to some abstraction, like custom Map interface with suspend methods) Any attempt to avoid using channels in this case as result will be just simplified implementation of channels
d
It's basically being used as caches in Ktor, so it's a pity to instantiate tons of objects per request to the cache... but I still want Ktor to continue serving requests of things that are already in the cache.
l
Well, if you would access this map from within of
withContext(IO) {...}
, then I think you will get the behaviour you're describing. With that you could write an extension suspending function for
Map
in general (or
ConcurrentHashMap
specifically), which could do the get operation in this fashion automatically.
So perhaps something like this? https://pl.kotl.in/HJ4b5xIp7
d
I was thinking more along the lines of using a Mutex with a regular MutableMap.. I'm not sure of it's any better though.
g
I don't think that Mufex is somehow better
To be honest I never see good usages for coroutines Mutex, usually code with channel is more simple and safe
But use MutableMap managed by actor is definitely make sense
t
Using coroutine for implementing concurrent containers is toppling overhead. Because Coroutine abstracts the implementation of dispatcher, you can not estimate the processing cost of the Concurrent container. For example, the current implementation of Dispatchers.IO is a LimitingDispatcher that uses ConcurrentLinkedQueue. In this way you can not escape from "java.util.concurrent. *" Just by adding extra overhead.
d
That's why I thought it might be nice to have some kind of Coroutines primitive for this. It would seem to me that all the object allocations for each get/set call in an actor, would overweigh the benefits....
t
Coroutine itself is just continuation. also dispatcher is just codes to use continuation. even if you move some codes to built-in, it does not make fast your code. there is no magic.
d
Not blazing fast, but suspendable and not wasteful 🙂. The use case is a cache, which in itself takes up lots of memory, to add all the object instantiation and GCing, might not be a good idea. On the other hand, the regular implementation blocks instead of suspending meaning that less requests can be dealt with while loading elements into the cache, even though there might be what these requests need already there...
d
Java's GC is blazing fast nowadays. It really is. C# is far behind in this regard. Stop assuming that object allocation will slow stuff down. Short allocations might be placed on the stack, even.
Do some testing is what I'm saying.