Get atom state and reset atomize

I am writing a Mandelbrot Set , and to speed up figuring out which points go to infinity, I decided to try a ExecutorService to check for parallel points.

Basically, the plan is as follows:

  • Calculate all the points I need to find
  • Specify each service point
  • Ask the service to wrap your results in an Atom a vector wrapper as you create them.
  • Periodically create a drawing code to get the results and clear the queue

My problem is with the last point. How can I safely capture previous results from an atom and reset it?

I thought of a simple way simply:

 (def draw-queue-A (atom [])) (defn grab-and-clear-queue [] (let [results @draw-queue-A] (reset! draw-queue-A []) results)) 

But it does not look safe. If between dereferencing and reset! something added, it will be lost.

The ominous abomination that I stopped at the moment:

 (defn grab-and-clear-queue [] (let [results (atom [])] (swap! draw-queue-A (fn [res] (reset! results res) [])) results)) 

But using an atom just to get results seems ridiculous.

How can I safely extract the contents of an atom and reset without losing any results?

+5
source share
2 answers

One simple answer is to use Clojure ref instead of atom . It allows you to block a value for more than one function call (unlike swap ):

 (ns tst.clj.core (:use clj.core clojure.test tupelo.test) (:require [tupelo.core :as t] )) (t/refer-tupelo) (t/print-versions) (def results (ref [])) (future (doseq [i (range 10)] (dosync (Thread/sleep 20) (alter results t/append i)))) (defn get-and-clear [] (dosync (let [curr-results @results] (ref-set results []) curr-results))) (doseq [i (range 10)] (Thread/sleep 50) (spyx (get-and-clear))) 

with the results:

 ------------------------------------- Clojure 1.8.0 Java 1.8.0_111 ------------------------------------- (get-and-clear) => [0 1] (get-and-clear) => [2 3] (get-and-clear) => [4] (get-and-clear) => [5 6] (get-and-clear) => [7] (get-and-clear) => [8 9] (get-and-clear) => [] (get-and-clear) => [] (get-and-clear) => [] (get-and-clear) => [] 

Other options include using the queue from clojure.core.async or a simple Java-safe queue.

Depending on the format of your problem, you can also use a Python-style generator function, as described here.

+1
source

There is currently a JIRA ticket dedicated to this very request. At the same time, it does what you want, and it looks like the one in the patch, although I was only looking at the code:

 (defn reset-return-old! [atm new-value] (let [old-value @atm] (if (compare-and-set! atm old-value new-value) (do (.notifyWatches atm old-value new-value) old-value) (recur atm new-value)))) 

We rely on CAS semantics, as well as swap! . We are spinning effectively to ensure that we are not interrupted between reading and CAS (although I believe that this is still the victim of the problem

+6
source

Source: https://habr.com/ru/post/1267110/


All Articles