2

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)

h3x3d
  • 231
  • 2
  • 10

3 Answers3

3

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.

Community
  • 1
  • 1
dsm
  • 10,263
  • 1
  • 38
  • 72
2

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.

Community
  • 1
  • 1
Michał Marczyk
  • 83,634
  • 13
  • 201
  • 212
0

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))
Arthur Ulfeldt
  • 90,827
  • 27
  • 201
  • 284
  • The question is about multithreaded environment, not just take subvec. – h3x3d Oct 18 '13 at 15:07
  • 1
    `clojure.core/subvec` holds on to the underlying vector, so this would prevent all entries from becoming eligible for GC indefinitely. (In contrast, `clojure.core.rrb-vector/subvec` does perform a real slice, discarding entries outside of the given index range.) – Michał Marczyk Oct 18 '13 at 17:29