Thanks for the response and discussion. Your proposal solves the problem,
but not the general observation: that timeout channels are not usable keys.
A small tweak on your proposal can make a key-safe channel:
(defn unique-timeout
[ms]
(let [c (chan)]
(take! (timeout ms) (fn [_] (close! c)))
c))
(do (loop [ch->v (into {} (for [v [1 2 3]] [(unique-timeout 1000) v]))]
(when-let [chs (keys ch->v)]
(let [[_ ch] (alts!! chs)]
(println (ch->v ch))
(recur (dissoc ch->v ch)))))
(println "done"))
I think the lesson learned is, that the implementation of timeout-channels
favours efficiency over the possibility of storing them in maps or sets,
and removing them from these datastructures in a loop.
Once again, thanks for all the feedback!
Thomas
On Wednesday, November 20, 2013 10:53:45 AM UTC, Michał Marczyk wrote:
>
> As for scheduling the printlns, this prints out 1, 2, 3 (in some order):
>
> (let [c (chan)]
> (doseq [v [1 2 3]]
> (take! (async/timeout 1000) (fn [_] (put! c v))))
> (go-loop [v (<! c)]
> (println v)
> (recur (<! c))))
>
> Cheers,
> Michał
>
>
> On 20 November 2013 11:34, Michał Marczyk <[email protected]<javascript:>>
> wrote:
> > The behaviour of timeout channels is to close after the timeout
> > elapses. This will be visible everywhere the channel is used.
> >
> > Cheers,
> > Michał
> >
> >
> > On 20 November 2013 11:22, Cedric Greevey <[email protected]<javascript:>>
> wrote:
> >> Isn't that not only violating least astonishment, but potentially
> >> introducing a terrible bug into the library? One could use "two
> different"
> >> timeout channels in two different alts, and if the timeout channels are
> >> aliased, then perhaps only one of the alts would actually get notified.
> >>
> >>
> >> On Wed, Nov 20, 2013 at 5:05 AM, Michał Marczyk
> >> <[email protected]<javascript:>>
>
> >> wrote:
> >>>
> >>> The reason = considers you timeout channels to be equal is that they
> >>> are, in fact, the same object. In fact, they may end up being the same
> >>> object even with different timeout values:
> >>>
> >>> (identical? (timeout 1) (timeout 2))
> >>> ;= true
> >>>
> >>> Except I got a false just now with a fresh REPL and same timeout
> >>> value... All subsequent invocations return true though, and I'm sure
> >>> with a little digging the reason for the false would become clear.
> >>>
> >>> The reason for them being the same object is that timeout goes out of
> >>> its way to avoid creating to many timeout channels and will reuse
> >>> existing ones if their timeouts are due within a small amount of time
> >>> (clojure.core.async.impl.timers/TIMEOUT_RESOLUTION_MS, currently 10
> >>> ms) of the requested timeout.
> >>>
> >>> Cheers,
> >>> Michał
> >>>
> >>> On 20 November 2013 10:08, Thomas G. Kristensen
> >>> <[email protected] <javascript:>> wrote:
> >>> > Hi all,
> >>> >
> >>> > I ran into a core.async behaviour that confused me a bit the other
> day.
> >>> > In
> >>> > some of our systems, we need to fire different timeouts, perform
> actions
> >>> > and
> >>> > schedule a new timeout. The problem is, that if the timeouts are of
> the
> >>> > same
> >>> > number of ms, we can't distinguish them, and therefore not keep
> track of
> >>> > and
> >>> > remove them from a set (at least not easily).
> >>> >
> >>> > That sounds a bit fuzzy. Hopefully this spike will make it clearer
> what
> >>> > I'm
> >>> > trying to say:
> >>> >
> >>> > (require '[clojure.core.async :refer [chan timeout alts!! alts!]])
> >>> >
> >>> > (= (chan) (chan))
> >>> > ;; false
> >>> >
> >>> > (= (timeout 1) (timeout 2))
> >>> > ;; false
> >>> >
> >>> > (= (timeout 1) (timeout 1))
> >>> > ;; true
> >>> >
> >>> > (do (loop [ch->v (into {} (for [v [1 2 3]] [(timeout 1000) v]))]
> >>> > (when-let [chs (keys ch->v)]
> >>> > (let [[_ ch] (alts!! chs)]
> >>> > (println (ch->v ch))
> >>> > (recur (dissoc ch->v ch)))))
> >>> > (println "done"))
> >>> > ;; only fires "3", the last channel in the map
> >>> >
> >>> > The intended behaviour of the last loop is to print 1, 2 and 3 (not
> >>> > necessarily in that order). However, the ch->v map will only contain
> one
> >>> > key, as timeouts with the same duration are considered the same
> value.
> >>> > In
> >>> > the real example, a new timeout with the same value should be
> scheduled
> >>> > again, by being put in the map.
> >>> >
> >>> > So, my questions are:
> >>> >
> >>> > - Is this intended behaviour?
> >>> > - Is there a different pattern for achieving the scheduling
> behaviour
> >>> > I'm
> >>> > looking for?
> >>> >
> >>> > Thanks for your help,
> >>> >
> >>> > Thomas
> >>> >
> >>> > --
> >>> > --
> >>> > You received this message because you are subscribed to the Google
> >>> > Groups "Clojure" group.
> >>> > To post to this group, send email to
> >>> > [email protected]<javascript:>
> >>> > Note that posts from new members are moderated - please be patient
> with
> >>> > your
> >>> > first post.
> >>> > To unsubscribe from this group, send email to
> >>> > [email protected] <javascript:>
> >>> > For more options, visit this group at
> >>> > http://groups.google.com/group/clojure?hl=en
> >>> > ---
> >>> > You received this message because you are subscribed to the Google
> >>> > Groups
> >>> > "Clojure" group.
> >>> > To unsubscribe from this group and stop receiving emails from it,
> send
> >>> > an
> >>> > email to [email protected] <javascript:>.
> >>> > For more options, visit https://groups.google.com/groups/opt_out.
> >>>
> >>> --
> >>> --
> >>> You received this message because you are subscribed to the Google
> >>> Groups "Clojure" group.
> >>> To post to this group, send email to [email protected]<javascript:>
> >>> Note that posts from new members are moderated - please be patient
> with
> >>> your first post.
> >>> To unsubscribe from this group, send email to
> >>> [email protected] <javascript:>
> >>> For more options, visit this group at
> >>> http://groups.google.com/group/clojure?hl=en
> >>> ---
> >>> You received this message because you are subscribed to the Google
> Groups
> >>> "Clojure" group.
> >>> To unsubscribe from this group and stop receiving emails from it, send
> an
> >>> email to [email protected] <javascript:>.
> >>> For more options, visit https://groups.google.com/groups/opt_out.
> >>
> >>
> >> --
> >> --
> >> You received this message because you are subscribed to the Google
> >> Groups "Clojure" group.
> >> To post to this group, send email to [email protected]<javascript:>
> >> Note that posts from new members are moderated - please be patient with
> your
> >> first post.
> >> To unsubscribe from this group, send email to
> >> [email protected] <javascript:>
> >> For more options, visit this group at
> >> http://groups.google.com/group/clojure?hl=en
> >> ---
> >> You received this message because you are subscribed to the Google
> Groups
> >> "Clojure" group.
> >> To unsubscribe from this group and stop receiving emails from it, send
> an
> >> email to [email protected] <javascript:>.
> >> For more options, visit https://groups.google.com/groups/opt_out.
>
--
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.