Is using `AtomicRef` and `Deferred` a good approac...
# coroutines
m
Is using
AtomicRef
and
Deferred
a good approach to ensure that concurrent calls to
update()
never cause more than one
updateAsync()
execution in parallel? For example let’s say
updateAsync()
execution takes 10 seconds and there are 4 calls to
update()
with 2 seconds in between.
updateAsync()
would only be called once and they all share the same result, right?
d
The code you have might call
updateAsync()
multiple times. (Unless it's just an illustration then nvm). The function pass to
updateAndGet
should be pure.
Instead of
AtomicRef
, I think you should use a
Semaphore
.
m
What do you mean by pure?
d
Without side effect. As the lambda could be executed multiple times.
m
Oh, really. Damn. It launches a coroutine 😅
d
Haha yeah. You could have 8 `updateAsync()`s running concurrently without it's result being consumed.
m
I guess I have to fall back to a
Mutex
then?
Mutex
basically seems to be a
Semaphore
with
permits = 1
, doesn’t it?
d
It is but
Semaphore
was quite recently optimised and currently performs better than
Mutex
. (I checked this a month ago, not sure if
Mutex
has been updated since).
m
Interesting. Thanks for the heads ups 🙂
c
What’s the intention here? Is it that if
updateAsync
is running that it won’t try to update again? Or that new updates cancel/replace the previous one? There are a handful of things you can do with Channels or Flows that can solve both those cases pretty elegantly
m
New update requests should join the current pending update. I’ve already rewritten it as a Flow 🙂
d
If you've got time or can be bothered. Can you share the rewrite? I can't imagine how this can be rewritten with a
Flow
.
m
It’s merged with other functionality by now, esp. caching. So the behavior has changed slightly which makes it work with Flows 🙂
It now comes close to something like
flow { while(true) { emit(update()); delay(refreshInterval) } }.stateIn(…)
d
Ah,
stateIn
off course, that makes a lot of sense.