What does it mean for readers to have their own timeline - clojure

In his talk are we there yet, at 57:25, Rich Hickey talks about multiversion concurrency control. One of the advantages listed is the ability for readers to have their own timeline. I'm curious what this means in practice. Is this done by simply letting the reader save a history of observed values? Or is it somehow done with the help of of clojure's STM? It would be nice to see an example of how this is used in clojure.

I think Rich meant that readers outside a transaction see the world as it is in it's current state every time they try to read a value and this world view is individual for each of them.
When you've got two uncorrelated functions (not bound in the same transaction) trying to get current value of a variable (atom, ref, agent, etc...), they are not guaranteed to obtain (see) the same value.
Example:
(let [
; 1.
counter (ref 0)
; 2.
_ (.start (Thread. (fn [] (while (< #counter 1000000)
(dosync (alter counter inc))))))
_ (Thread/sleep 10)
; 3.
_ (let [r1 #counter
_ (Thread/sleep 1)
r2 #counter]
(println "free reader 1: " r1 "free reader 2:" r2))
; 4.
_ (dosync (let [r1 #counter
_ (Thread/sleep 1)
r2 #counter]
(println "frozen reader 1: " r1 "frozen reader 2:" r2)))
_ (println "---------------------------------")])
sample output:
free reader 1: 30573 free reader 2: 31295
snapshot reader 1: 105498 snapshot reader 2: 105498
---------------------------------
free reader 1: 37567 free reader 2: 38369
snapshot reader 1: 181392 snapshot reader 2: 181392
---------------------------------
free reader 1: 37317 free reader 2: 88570
frozen reader 1: 467471 frozen reader 2: 467471
---------------------------------
How it works:
Declare a counter variable as ref (transactional variable type) and set its initial value to 0
Create Java thread with anonymous function that changes the counter by incrementing it in a loop and ".start" the thread.
Read counter in a two step way, separated by 1 ms delay and print each value. As you can see both values are different as expected. This simulates separate time lines, when two objects observing the same object receive different data.
The same as above but in a world snapshot. Putting sleep function does not effect the output values. Both of them are equal.

Related

Putting then immediately removing value from channel causes weird behavior (ClojureScript core.async)

The following is a contrived example for learning purposes. It involves jamming the value "val" into a channel and then immediately removing it within a go block:
(def test-chan1 (chan))
(go
(println
(<!
(go
(do
(>! test-chan1 "val")
(<! test-chan1)))))) ; the return value of the (do..) is "val"
; ...hence the return value of the nested go block should be a channel containing "val"
; hence (println ..) should eventually print "val" to the console
Question: Why does this code snippet not print "val" to the console?
Channels by default are synchronous, so a put will block until there is somebody to get (and the other way around).
So Your problem is that the inner go is blocked on the put (>!) forever. Try changing your channel to (channel 1).

run sql in parallel using future: but the sql is not executed

I have the following function
(defn run [x]
(doseq [i (range 1 x)]
(println i)
(future (j/execute! vertica-db ["insert /*+ direct */ into a select * from a limit 1"]))
))
when call it using
(run 100)
it will print 1..99, however if check the row number of table a, the row number is not increased which mean the sql is not executed. How to run the sql in parallel?
The only suspicious thing I see in your code is the fact that you never wait for the futures to finish (so maybe they don't ?).
You need to collect the values returned by future calls and then block until they finish by using (deref f)/#f (i.e. dereferencing the future) where f is one of those values.
Something like this should work:
(defn run [x]
(let [db-insert (fn [i] ((println i) (future (j/execute! vertica-db ["insert /*+ direct */ into a select * from a limit 1"]))))
inserts (doall (map db-insert (range 1 x)))] ;force execution of all the db-insert calls
(doseq [insert inserts] #insert))) ;wait for all the futures to finish

clojurescript core.async - tell if mouse is down while mouseover

I am looking for a nice way of only responding to mouseover events but only when the mouse is down. I'm looking for a more core.async way of doing this.
I have two channels in an om component:
om/IDidMount
(did-mount [_]
(let [canvas (q ".tutorial")
_ref (js/Firebase. "https://conseal.firebaseio.com/scribble")
ctx (.getContext canvas "2d")
mouse-down (om/get-state owner :mouse-down)
mouse-chan (om/get-state owner :mouse-chan)]
(listen canvas EventType.MOUSEDOWN #(put! mouse-down [:down %]))
(listen canvas EventType.MOUSEMOVE #(put! mouse-chan [:move %]))
I then have the following go-loop in IWillMount:
om/IWillMount
(will-mount [_]
(let [mouse-down (om/get-state owner :mouse-down)
mouse-chan (om/get-state owner :mouse-chan) ]
(go-loop []
(<! mouse-down)
(let [[evt-type e] (<! mouse-chan)]
(.log js/console (str evt-type " we are over " e)))
(recur))))
The above does not work because mousedown events are not continually sent. I'm looking for a core.async idiomatic way of handling this.
If I was using rxjs I could do something like this:
var mouseDrags = mouseDowns.select(function (downEvent) {
return mouseMoves.takeUntil(mouseUps).select(function (drag) {
return functionToGetStuffWeWant(drag);
});
});
Keeping your current code structure, one way to do this is to add a mouse-up channel (or combine this with mouse-down into a mouse-buttons channel or something).
Then in your go loop, use the following logic:
Read from mouse-down and mouse-channel (using alt). If mouse-channel was read, ignore the value and loop (to 1). If mouse-down was read, break out of the loop and continue with 2.
Read from mouse-up and mouse-channel. If mousechannelwas read, process the current position and loop (to 2). Ifmouse-up` was read, break out of the inner loop, and loop back to 1.
To put this in concrete terms, you might do something like this (untested):
(go-loop []
(loop []
(alt! [mouse-down] down nil ;; stop looping when mouse-down is read
[mouse-channel] event (recur))) ;; loop until mouse-down
(loop []
(alt! [mouse-up] up nil ;; stop looping when mouse-up is read
[mouse-chan] event ;; process current position
(do
(.log js/console (str evt-type " we are over " event))
(recur)))) ;; loop until mouse-up
(recur)) ;; start the process all over again
For robustness, you may want to read from mouse-up in the first loop and mouse-down in the second loop, in case there are ever two consecutive mouse-up (or mouse-down) events. Otherwise, it's possible for them to get out of sync. In both cases, simply discard the value and recur.
On the other hand, you may prefer an approach similar to your rxjs example. In this case, note that several of the seq operations (map, take, etc) from core clojure have channel analogs in core.async. However, I don't think take-until is one of them. Still, it should be pretty easy to implement your own version of take-until that operates over channels.

Are refs really consistent within a STM transaction?

I read at clojure.org/refs that
All reads of Refs will see a consistent snapshot of the 'Ref world' as of the starting point of the transaction (its 'read point'). The transaction will see any changes it has made. This is called the in-transaction-value.
There's also a link to Snapshot Isolation on wikipedia that implies that reads of any number of refs will be consistent with each other once a transaction has started.
I made a test case...
(def r1 (ref 0))
(def r2 (ref 0))
(defn delay-then-inc-ref [id ref delay]
(.start
(Thread.
#((println id " start")
(Thread/sleep delay)
(dosync
(alter ref inc))
(println id " end")))))
(defn deref-delay-deref [ref1 ref2 delay]
(.start
(Thread.
#((println "S start")
(dosync
(let [a #ref2]
(Thread/sleep delay)
(println "S r1=" #ref1))) ; #ref1 consistent with #ref2 ?
(println "S end")))))
*clojure-version*
;=> {:major 1, :minor 3, :incremental 0, :qualifier nil}
(deref-delay-deref r1 r2 2000)
(delay-then-inc-ref "1" r1 500)
(delay-then-inc-ref "2" r1 1000)
(delay-then-inc-ref "3" r1 1500)
The output is:
S start
1 start
2 start
3 start
1 end
2 end
3 end
r1 = 3
S end
nil
The value of r1 = 3 rather than r1 = 0 suggests that in deref-delay-deref the deref of ref1 after the sleep is picking the value of r1 after the three delay-then-inc-ref transactions have occurred.
Note that I know about ensure to prevent updates to refs by other transactions during a particular transaction, but I don't believe that applies here. I don't care if ref1 changes as long as I see a value consistent with the start of my transaction.
How does this behaviour fit with the above referenced documentation?
It turns out that if the ref has some history it behaves as I expect, so changing the ref declaration to add a :min-history and then setting both refs as shown, seems to make it work....
(def r1 (ref 0 :min-history 5))
(def r2 (ref 0 :min-history 5))
(dosync
(ref-set r1 0)
(ref-set r2 0))
Then the output is:
S start
1 start
1 end
2 start
2 end
3 start
3 end
S r1= 0
S end
nil
Reading here, it's clear what's going on. The read transaction is restarting because there is no entry in the ref history from before the transaction started. To confim I added some more logging:
(defn deref-delay-deref [ref1 ref2 delay]
(.start
(Thread.
#((println "S start")
(dosync
(println "transaction starting")
(let [a #ref2]
(Thread/sleep delay)
(println "S r1=" #ref1))) ; should be consistent with #ref2
(println "S end")))))
Output without history mods:
S start
transaction starting
1 start
2 start
3 start
1 end
2 end
3 end
transaction starting
S r1= 3
S end
and with history mods:
S start
transaction starting
1 start
2 start
3 start
1 end
2 end
3 end
S r1= 0
S end
nil
UPDATE: It turns out my answer above is something of a distraction because of the artificial nature of the test case. In real world usage it doesn't matter whether the transaction re-starts or not, since the transactions MUST be written such that they are re-startable. The runtime provides no guarantees about whether read only transactions will complete in the presence/absence of history. Rather it can do whatever's necessary to get the world of transactions to complete and the transaction code MUST be written with this in mind. More detailed discussion here
I'm leaving the above for reference.

How can I lazily evaluate read-line to gather input?

(The following was originally a homework assignment, but I'm trying it in a new language.)
In a short Clojure program, I attempt to generate a lazy sequence of inputs (from the command line) and from them calculate three character values. I would assume that, possibly depending on how Clojure chose to evaluate my let bindings, this ought to produce a prompt series like the following:
$ clj lazy-prompts.clj
Enter value #1: 32
Enter value #3: 162
Enter value #2: 12
Enter value #4: 118
a A 5
Instead, the program begins and hangs infinitely with no prompts. I tried eagerly evaluating the for expression by wrapping it in dorun, but that did not change the outcome.
Why does the following program produce no input prompts?
(use '[clojure.java.io :only (reader)])
(def of-input
(for [value-number [1 2 3 4]]
(dorun
(print (str "Enter encrypted value #" value-number))
(read-line)
)))
(let [value-1 (nth of-input 1)
value-2 (nth of-input 2)
value-3 (nth of-input 3)
value-4 (nth of-input 4)]
(let [a (/ (+ value-1 value-3) 2)
b (/ (+ value-2 value-4) 2)
c (- value-4 b)]
(println (char a) (char b) (char c))))
First, you should replace dorun with do. The former expects a seq as its first or second argument and forces it.
After that change, the code more or less runs correctly. What you observe as "hanging" is actually waiting for your input. One of the problems is, that you don't see the prompts (yet). They actually show, but only after you enter four values. How do you fix that? I don't know, I always thought that having side effects in a lazy sequence is a bad idea, so I never do that.
The other problem is, that read-line returns strings and you're using them as numbers. You'll have to convert them first.
P.S. "for" in clojure is not a for-loop, it is a list comprehension.
print does not flush the output, so you don't see the prompts immediately. Either use println or call flush explicitly, like so:
(def of-input
(for [value-number [1 2 3 4]]
(dorun
(print (str "Enter encrypted value #" value-number))
(flush)
(read-line)
)))