Hi Brian,
I had the same requirement while building an application, it included a GUI
and I wanted to perform some actions only after the user was done editing
some text. I also first implemented a solution using an atom, Thread/sleep
and a future. It didn't seem right though, since I was creating a bunch of
threads all the time, so I tried an approach with the tools core.async
provides and the result was the following:
(defn timeout-channel
"Creates a channel and a go block that takes from it. The go block keeps
an internal status with two possible values, `:wait` and `:receive`.
In ':wait' status, execution is blocked until there's a value available in the
channel, it then enters the ':receive' status, until the timeout wins.
Returns the channel where events need to be pushed."
[timeout-ms f]
(let [c (async/chan)]
(async/go-loop [status :wait
args nil]
(condp = status
:wait
(recur :receive (async/<! c))
:receive
(let [[_ ch] (async/alts! [c (async/timeout timeout-ms)])]
(if (= ch c)
(recur :receive args)
(do
(async/thread (if (sequential? args) (apply f args) (f args)))
(recur :wait nil))))))
c))
Signalling the go block to terminate when the event source is no longer
available is missing, but that simple enough to implement. Maybe this is
something you can use as a starter point.
Hope it helps,
Juan
On Monday, December 1, 2014 6:37:56 PM UTC-3, Brian Craft wrote:
>
> I have need to perform an action when a series of events is quiet for some
> period. That is, if one event arrives an action is queued to execute after
> some timeout. If a second event arrives the timeout is reset, and so-forth.
>
> The following code seems to work, however I'm wondering if calling
> 'future' from 'swap!' is a bad idea (side effecting), and if there's a
> better way.
>
> (defn queue-with-delay [period func]
> (let [f (atom nil)]
> (fn []
> (when @f
> (future-cancel @f))
> (swap! f (fn [_] (future (Thread/sleep period) (func)))))))
>
>
> Use like
>
> (def event (queue-with-delay 2000 #(println "running")))
> (event)
> (event)
> (event) ; pause 2 sec
> "running"
>
>
>
>
--
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/d/optout.