Reputation: 231
The thing i need - is simple queue, something, where i can put tasks, and retrieve them one-by-one from workers(without maintaining order of tasks).
I wrote something like this:
;; Definition
(def q (ref []))
;; Put
(defn put-in-queue [i]
(dosync (alter q conj i)))
;; Get
(defn get-from-queue []
(dosync
(let [v (peek q)]
(alter q pop)
v)))
Is it correct solution? (maybe there are also better solutions for this task)
Upvotes: 2
Views: 1905
Reputation: 84331
The correct solution is probably to use a java.util.concurrent
queue, most likely java.util.concurrent.LinkedBlockingQueue
. j.u.c
queues are robust, perfectly suited to the task and work in Clojure just fine.
See my answer to the Producer consumer with qualifications SO question for a scenario with 5 producers, 2 consumers and a limited-size queue implemented in two ways for comparison: first with c.l.PersistentQueue
, second with j.u.c.LinkedBlockingQueue
.
Upvotes: 2
Reputation: 91544
as dsm points out, when you need a queue, use a queue, and for times where you really need a vector and want to add things to the end and remove them from the front, subvec
and conj
are both O(1) functions on vectors.
user> (subvec [1 2 3] 1)
[2 3]
user> (conj [1 2 3] 4)
[1 2 3 4]
user> (-> [] (conj 1 2) (conj 3) (subvec 1))
Upvotes: 0
Reputation: 10403
You should use a clojure.lang.PersistentQueue
, right tool for the job and all that :).
Sample below "borrowed" from Hidden features of Clojure:
user> (-> (clojure.lang.PersistentQueue/EMPTY)
(conj 1 2 3)
pop)
(2 3)
See the remainder of that answer for specifics.
Upvotes: 3