This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-04-11
Channels
- # admin-announcements (2)
- # beginners (53)
- # boot (151)
- # cider (11)
- # cljs-dev (60)
- # cljsrn (36)
- # clojure (71)
- # clojure-austin (13)
- # clojure-berlin (2)
- # clojure-czech (11)
- # clojure-dev (35)
- # clojure-dusseldorf (2)
- # clojure-france (6)
- # clojure-japan (9)
- # clojure-russia (183)
- # clojure-uk (18)
- # clojurescript (155)
- # cursive (6)
- # datomic (25)
- # euroclojure (6)
- # funcool (6)
- # hoplon (229)
- # instaparse (10)
- # jobs (9)
- # leiningen (5)
- # off-topic (70)
- # om (29)
- # onyx (18)
- # planck (1)
- # proton (5)
- # re-frame (8)
- # reagent (32)
- # untangled (4)
@roman01la: I saw your CA and have added the edit roles
@alexmiller: thanks!
I’m wondering why is core.async timeout implemented using SkipList[1]. I would expect implementation using javascript setTimeout function would be straightforward and just few lines of code. I’m asking because I started to rely on timeout heavily and sometimes my timeout channels close early without apparent reason (non-deterministic). Maybe I hit some bug in SkipList implementation. [1] https://github.com/clojure/core.async/blob/master/src/main/clojure/cljs/core/async/impl/timers.cljs
ok, I’m going to implement my dumb version using setTimeout to see if my problems go away
the problem happens when I have a lot of timers “in-flight” and then refresh the page and it creates bunch of more timers, and then I refresh again, second, third or fourth refresh usually has a failing timeout which closes early (like after 100ms-200ms, instead of 5000ms)
ok, I was just speaking that I’m sure I’m passing proper time-limit in msec for them to close
I will now do an experiment and not pass 5000 all the time, I will pass numbers 100ms apart from each other, to prevent coallescing
while you can experiment with this, rest assured I spent ridiculous amounts of time on this problem
it has the worst behavior and performance characteristics of the various ways to get into the event queue
ok, when I make sure that my timeouts are descending and 100ms apart each other, the problem goes away
so it seems my problem lies in that coalescing logic, when I create multiple timeouts in quick order with the same msec parameter and they get coallesced
What's the recommended way of getting setTimeout behavior?
can you explain why coallescing leads to unexpected channel close before timeout interval? I still don’t understand why it behaves this way. I would expected coallesced events would share a channel, but would still work as expected (closed after 5000ms in my case even if the channel returned from timeout call can be potentially shared with someone else)
ok, now I understand what went wrong. I had a completely unrelated code which was creating a timeout channel and closing it when it was no longer needed (after receiving a message "in time"). In those rare occasions when someone else created timeout which by coincidence coalesced with that one bad things started to happen. Forcible close of the channel closes unexpectedly the channel for others BEFORE timeout elapsed.
lesson learned: never ever close! channel received from (timeout …) calls, it is unsafe
this one was tricky to track down, because when I added console.log statements, or reshaped code a bit, the issue was no longer reproducible
@darwin you might want to confirm that the behavior is actually the same between Clojure & ClojureScript - it may be a bug in ClojureScript
well, if the channel is reused, how can the library tell who called the close!, close will simply close the channel for all who share it
I didn’t initially understand that coalescing can have effect on me as a user, I didn’t get it, because the model in my head was “it is just an implementation detail - optimization"
right but from one perspective calling close on a timeout channel seems possibly strange, the coalescing stuff aside
well, my naive model in my head was “there is a table of all timeouts” which holds references to future timeouts, if I close them and forget, it will get garbage-collected
closing is very much a special case since everyone blocked on reads will immediately progress
so how can I possibly “cancel” a scheduled timeout if I know I don’t want to handle it anyways and I want to garbage-collect it ASAP, I just forget about it, there is no”callback" which will fire at some point in the future?
btw. I rewrote my original code with alts!
https://github.com/binaryage/dirac/commit/183ce1b20f2c571c43bd65b9fe5563abced96ff7
that is hopefully safe, but still I think the original reasoning wasn’t obviously wrong, I got a channel, so I close it when I don’t need it anymore