Why do transactions block each other?
My understanding of transactions is that they don't block each other even when the same refs are involved. Obviously, I'm wrong, see the following scenario: user=> (def thread (agent "Thread")) #'user/thread user=> (def account (ref 1000)) #'user/account user=> (send thread (fn [agt aref] (dosync (alter aref + 100) (Thread/sleep 8000) agt)) account) # user=> (time (dosync (ref-set account 2000))) "Elapsed time: 6838.605366 msecs" 2000 Trying '(dosync (ref-set account 2000))' while the thread is running blocks the REPL. Interestingly, the threaded transaction isn't retried as a effect of changing the ref-value while the threaded-transaction is still running. My understanding is that the threaded transaction tries to commit *after* Thread/sleep, realizes a changed value for account and retries the transaction. (BTW, if 'alter' is replaced by 'commute', the REPL does not block.) What's really going on behind the scenes? What am I missing? Cheers, Dominikus -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Why do transactions block each other?
Hi Dominikus, I think what you're seeing here is that transactions are synchronous from the point of view of the calling thread. Within your REPL thread, it is guaranteed that the transaction has committed before the `dosync` block returns. So even if transactions are getting aborted and retried behind the scenes, the thread that initiated the transaction still blocks until it is finished. As to which transaction "wins", I'm not sure what the rule is. -Stuart Sierra clojure.com -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: ClojureScript can't call JavaScript functions relying on `this`
On Sun, Aug 28, 2011 at 9:22 PM, Kevin Lynagh wrote: > I am having trouble using ClojureScript to call JavaScript functions > that exploit prototype injection. > If I'm reading `defmethod :emit invoke` correctly, > > > https://github.com/clojure/clojurescript/blob/master/src/clj/cljs/compiler.clj#L513 > > ClojureScript always seems to compile f(x) JavaScript calls as > > f.call(null, x) > > which trip up any functions that rely on `this` to have certain > properties. > I have two questions: > > 1) why are function calls compiled to the `f.call(null, ...)` form > rather than just `f(...)`? Is it to support the Closure Compiler? > > 2) What is the appropriate way to use JavaScript functions that rely > on `this`? > Is there some way to emit `f.call(f, ...)`, or do I need to use `(js* > "f(...)")`? > > For reference, here is a minimal JavaScript example of the JavaScript > prototype injection pattern: > > var p_injection = function(){}; > p_injection.one = function(){ return 1; }; > > var MyClass = function(){}; > > var x = new MyClass(); > x.two = function(){ return this.one() + 1; }; > x.__proto__ = p_injection; > x.two(); // 2 > x.two.call(null); // error, object has no method "one()" Have you tried calling the method using the interop form? (. x (two)) --Chouser -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Why do transactions block each other?
Hi, the commute case can be understood: user=> (send thread (fn [agt aref] (dosync (commute aref + 100) (Thread/sleep 8000) agt)) account) # user=> (time (dosync (ref-set account 2000))) "Elapsed time: 0.369415 msecs" 2000 user=> @account 2000 ;; wait a few seconds user=> @account 2100 So, the transaction run from the agent just recalculates the values at the end of the transaction again, based upon the value the ref has then. See LockingTransaction.java:290: vals.put(ref, f.fn.applyTo(RT.cons(vals.get(ref), f.args))); So in this case the ref-set from the REPL thread comes first. As for the other effect, that the REPL thread blocks until the eight seconds from the agent-transaction are finished, we can clearly see that the ref-set call is the last comitter, because the ref has the value 2000 afterwards: user=> (dosync (ref-set account 1000)) 1000 user=> (send thread (fn [agt aref] (dosync (alter aref + 100) (Thread/sleep 8000) agt)) account) # user=> (time (dosync (ref-set account 2000))) "Elapsed time: 5241.963286 msecs" 2000 ;; again wait a few seconds for good measure user=> @account 2000 I have to confess, that I don't understand that, yet. I was first guessing it could be related to the history, but the history is still zero: user=> (.getHistoryCount account) 0 Unless someone else answers this I will try to find some time to dive into it this evening (CEST). Adding a few atoms as counters here and there usually helps understanding, what is going on under the hooks. Regards, Stefan PS: Starting a thread with a transaction using future seems easier to me, e.g.: (future (dosync (alter account + 100) (Thread/sleep 8000))) -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Why do transactions block each other?
Hi, alter obviously has a similar effect as ensure. Exchanging the sleep and the alter will allow the repl thread to do its ref-set and the background thread will retry. Don't ask me for the details of why and how... Sincerely Meikel -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: is there a 4Clojure forum anywhere?
@Bob -- recovery group, stop now, -- hehehe. It certainly is a great website for when I get bored with the daily grind of enterprise- Java coding. I guess I was lucky to get stuck on one problem. -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
[ANN] Clojure 1.3 Beta 2
Clojure 1.3 Beta 2 is now available at http://clojure.org/downloads The list of changes: * clojure.test/*/*-report vars made dynamic for use with external tools. * Calls favor arg vectors :tag over var :tag (CLJ-811) * BigInt ops made faster when values are small enough to be treated as longs * rational? metadata fixed * partition and partition-all holds less * Bug fixed on transient vectors * print-dup and print-method removed for deftypes (CLJ-812) * Prevent make-parents NPE, (CLJ-808) * Special print support removed for BigIntegers. (CLJ-798) Please grab it and let us know how it works for you. Thanks! -- Chris Redinger Clojure/core http://clojure.com -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: ClojureScript can't call JavaScript functions relying on `this`
Chouser, Yes, that does it---I didn't even think about my use of (apply js/f args), thanks! Is there a way to use the interop form with variable-arity JavaScript functions without using `apply`? This issue came up with my ClojureScript wrapper for D3; I'm using this macro (defmacro shim [name] "Define a proxy to native D3 method" `(defn ~name [sel# & args#] (apply (. sel# ~name) args#))) to define proxy functions. If I can't use `apply` because of the `this = null` problem, do I have to write out a case for each arity? thanks, kevin On Aug 29, 6:24 am, Chouser wrote: > On Sun, Aug 28, 2011 at 9:22 PM, Kevin Lynagh wrote: > > I am having trouble using ClojureScript to call JavaScript functions > > that exploit prototype injection. > > If I'm reading `defmethod :emit invoke` correctly, > > > https://github.com/clojure/clojurescript/blob/master/src/clj/cljs/com... > > > ClojureScript always seems to compile f(x) JavaScript calls as > > > f.call(null, x) > > > which trip up any functions that rely on `this` to have certain > > properties. > > I have two questions: > > > 1) why are function calls compiled to the `f.call(null, ...)` form > > rather than just `f(...)`? Is it to support the Closure Compiler? > > > 2) What is the appropriate way to use JavaScript functions that rely > > on `this`? > > Is there some way to emit `f.call(f, ...)`, or do I need to use `(js* > > "f(...)")`? > > > For reference, here is a minimal JavaScript example of the JavaScript > > prototype injection pattern: > > > var p_injection = function(){}; > > p_injection.one = function(){ return 1; }; > > > var MyClass = function(){}; > > > var x = new MyClass(); > > x.two = function(){ return this.one() + 1; }; > > x.__proto__ = p_injection; > > x.two(); // 2 > > x.two.call(null); // error, object has no method "one()" > > Have you tried calling the method using the interop form? > > (. x (two)) > > --Chouser -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
ClojureScript and lein?
Hello, I wanted to give a try to ClojureScript but from Windows XP. Now I was doing all what is written on github but had to remove -server to obey "missing jvm.dll" problem (even after coping server path there was still a problem about loading some routine) and had to add to ENV Variables CLOJURESCRIPT_HOME with "D:/clojurescript/" (note the last /) Now I'm able to compile hello.cljs to hello.js and put reference to test.html but still it doesn't work. I think that there is some problem with relative paths. What I'm using is: JRE (not SDK since have problem with jvm as written above), Chrome as Browser and rest newest fetched with boostrap. My final thought is that running it is a nightmare and you wont gain critical mass to get some feedback from community. So the other thought is why can the lein do the job? Has anyone tried? I'm also a Mac user and probably in home all this howto will work, but in company where we all are using Windows there is no chance to get it working easily. In case you care how to set ENV Variable from batch on win32 it is: (defn set-env-variable [ name value] (console (str "Setting environment variable \"" name "\" to \"" value "\"")) (command "reg add HKCU\\Environment /v" name "/f /t REG_SZ /d" (str "\"" value "\""))) Where command is just a cmd (args are interposed with space) call and console is an output to cmd console. -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Why do transactions block each other?
The call to alter already wrote to the Ref, this requires a write-lock on the ref (see LockingTransaction.java/doSet). After that it sleeps a while and gets to its commit phase. The other transactions retries in the meantime. Consider the following code, which introduces some atoms for counting the retries (defn tz [] (let [rr (ref 10) a1 (atom 0) a2 (atom 0)] (println "Starting future") (future (dosync (swap! a1 inc) (alter rr + 100) (Thread/sleep 8000))) (println "Sleeping a bit") (Thread/sleep 1000) (println "Another dosync") (time (dosync (swap! a2 inc) (ref-set rr 1))) [@rr @a1 @a2 (.getHistoryCount rr)])) user> (tz) Starting future Sleeping a bit Another dosync "Elapsed time: 7001.554 msecs" [1 1 71 0] Note, how the 71 retries nice fit the approximately 7 seconds left and the 100 miliseconds time-out (LOCK_WAIT_MSECS) for the lock used in LockingTransaction.java/tryWriteLock. Transactions with significantly different run-times should be avoided, although there is some point at which older transactions will get their turn. This could be another explanation of the effect. Take a look at the barge-function in LockingTransaction.java Hope this helps, Stefan -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
get keys from defrecord
Hi, Assuming I have: (defrecord myrecord [:a :b :c]) is there a way to get the list of keys from the record definition? Thanks, Razvan -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: get keys from defrecord
user=> (defrecord MyRecord [a b c]) user.MyRecord user=> (def rec (user.MyRecord. "one" "two" "three")) #'user/rec user=> (keys rec) (:a :b :c) Cheers, Aaron Bedra -- Clojure/core http://clojure.com On 08/29/2011 12:54 PM, Razvan Rotaru wrote: Hi, Assuming I have: (defrecord myrecord [:a :b :c]) is there a way to get the list of keys from the record definition? Thanks, Razvan -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Why do transactions block each other?
Thanks a lot for this detailed analysis and the pointers to the Java implementation, Stefan! That's excellent and very helpful. I still wonder, why the first transaction blocks write access. My overall understanding of the transaction system is that changes to referenced values remain in-transaction before committing them, a write-lock shouldn't be needed. I'm surprised, that the second transaction is the one who has to retry 71 times even though the first transaction hasn't committed anything yet. Cheers, Dominikus P.S.: Thanks for the idea to use 'future' to spawn a thread! On Aug 29, 5:42 pm, Stefan Kamphausen wrote: > The call to alter already wrote to the Ref, this requires a write-lock on > the ref (see LockingTransaction.java/doSet). After that it sleeps a while > and gets to its commit phase. The other transactions retries in the > meantime. Consider the following code, which introduces some atoms for > counting the retries > > (defn tz [] > (let [rr (ref 10) > a1 (atom 0) > a2 (atom 0)] > (println "Starting future") > (future > (dosync > (swap! a1 inc) > (alter rr + 100) > (Thread/sleep 8000))) > (println "Sleeping a bit") > (Thread/sleep 1000) > (println "Another dosync") > (time > (dosync > (swap! a2 inc) > (ref-set rr 1))) > [@rr @a1 @a2 (.getHistoryCount rr)])) > > user> (tz) > Starting future > Sleeping a bit > Another dosync > "Elapsed time: 7001.554 msecs" > [1 1 71 0] > > Note, how the 71 retries nice fit the approximately 7 seconds left and the > 100 miliseconds time-out (LOCK_WAIT_MSECS) for the lock used in > LockingTransaction.java/tryWriteLock. > > Transactions with significantly different run-times should be avoided, > although there is some point at which older transactions will get their > turn. This could be another explanation of the effect. Take a look at the > barge-function in LockingTransaction.java > > Hope this helps, > Stefan -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: get keys from defrecord
Aaron Bedra writes: > user=> (defrecord MyRecord [a b c]) > user.MyRecord > user=> (def rec (user.MyRecord. "one" "two" "three")) > #'user/rec > user=> (keys rec) > (:a :b :c) I guess the problem with that is that you need to have an instance of the record before you can use `keys'. And to create an instance, at least you have to know the number of keys. However, you can inspect the record's constructor using reflection: (-> MyRecord .getConstructors first .getParameterTypes) This gets you an array of the record's parameter types. It seems, that the last 2 Object parameters are some internal stuff (metadata?), so the array length - 2 is the arity. (-> MyRecord .getConstructors first .getParameterTypes) ==> 5 ;; so the record has 3 keys If the record doesn't have fields hinted with primitive types, then that's enough knowledge to create an instance. If there are primitive type hints, then the constructor has primitive type parameters you have to match when calling it. All in all, it seems there's everything you need to create a function that creates a dummy instance of arbitrary (unknown) records that you can query for its keys afterwards. But maybe there's a better way... :-) Bye, Tassilo > On 08/29/2011 12:54 PM, Razvan Rotaru wrote: >> Hi, >> >> Assuming I have: >> >> (defrecord myrecord [:a :b :c]) >> >> is there a way to get the list of keys from the record definition? >> >> Thanks, >> Razvan >> -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Why do transactions block each other?
Hm, while I was just reading the source of the STM implementation in Ref.java and LockingTransaction.java two new questions came up for me. 1. Is there any use of the msecs field in the inner TVal in Ref? I don't see any and if it's not used anymore, at least two calls to System.currentTimeMillis() could be removed (one in Ref, the other in LockingTransaction). As far as I undestand, that call is considered expensive. 2. I found this post http://dow.ngra.de/2008/10/27/when-systemcurrenttimemillis-is-too-slow/ rather interesting to read and I wonder, whether such a thing could be used in bargeTimeElapsed() which is only interested in whether an interval has passed or not, too. Could this lead to a performance improvement? Kind regards, Stefan -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: JVM 7 support (invokedynamic)
Progress... is slow. I encouraged other people to try, so the least I can do now is to point you at some of the serious challenges. Right now I have what I think is a nice semi-generic mechanism for invokedynamic. It's called the "Linker": it handles finding the target method handle, bootstrapping, and what I call "restrapping", which is what happens when you guard it with an "ILinkable" (another new interface) and it fallbacks when a SwitchPoint is invalidated. There some various MethodHandle composing to make sure caller and target are both happy. I hope the "Linker" will make is easier to add invokedynamic in Clojure, and possibly in other projects. My real challenge is not there, however, but with adapting Clojure to JVM 7 more generally. invokedynamic requires V1.7 classes, and for V1.7 the stack frame map that was optional in V1.6 is now a requirement. This is overall a very good idea for moving the JVM forward (these maps are a huge help for HotSpot), but I have no doubt that it will create serious pain for any project that generates JVM bytecode and until JVM 7 now could afford to be sloppier with stack frames. The V1.7 verifier will simply not let you load classes that don't have perfectly aligned maps. ASM has very nice support for doing the stack frame arithmetic for you, but this is still being worked on in ASM 4 (trunk), and is not working in Clojure. I'm getting VerifyErrors specifically having to do with the mapping of try-catch blocks, and am working on debugging this via close look at CheckClassAdapter dumps. It's about as much fun as filling in tax forms. :/ (I've added support for two new defines, -Dclojure.jvm7=true and -Dclojure.invokedynamic=true, so each can be turned on separately. To be clear, my problems right now are in -Dclojure.jvm7=true and -Dclojure.invokedynamic=false.) I've already patched one tiny part of ASM commons in order to add support for invokedynamic, and my work on debugging this may result in a more major patch to ASM. Assuming I do manage a fix. :/ So, what can I say? It's the cutting edge, baby. In for a penny, in for a pound. -Tal -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: get keys from defrecord
Hi, it could help if you can provide more info on what you're trying to achieve 2011/8/29 Razvan Rotaru > Hi, > > Assuming I have: > > (defrecord myrecord [:a :b :c]) > > is there a way to get the list of keys from the record definition? > > Thanks, > Razvan > > -- > You received this message because you are subscribed to the Google > Groups "Clojure" group. > To post to this group, send email to clojure@googlegroups.com > Note that posts from new members are moderated - please be patient with > your first post. > To unsubscribe from this group, send email to > clojure+unsubscr...@googlegroups.com > 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 post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Why do transactions block each other?
2011/8/29 Dominikus > Thanks a lot for this detailed analysis and the pointers to the Java > implementation, Stefan! That's excellent and very helpful. > > I still wonder, why the first transaction blocks write access. My > overall understanding of the transaction system is that changes to > referenced values remain in-transaction before committing them, a > write-lock shouldn't be needed. I'm surprised, that the second > transaction is the one who has to retry 71 times even though the first > transaction hasn't committed anything yet. > I must confess this behaviour also challenges my assumptions. Does this work the same whatever the clojure version used ? > > Cheers, > > Dominikus > > P.S.: Thanks for the idea to use 'future' to spawn a thread! > > On Aug 29, 5:42 pm, Stefan Kamphausen wrote: > > The call to alter already wrote to the Ref, this requires a write-lock on > > the ref (see LockingTransaction.java/doSet). After that it sleeps a > while > > and gets to its commit phase. The other transactions retries in the > > meantime. Consider the following code, which introduces some atoms for > > counting the retries > > > > (defn tz [] > > (let [rr (ref 10) > > a1 (atom 0) > > a2 (atom 0)] > > (println "Starting future") > > (future > > (dosync > > (swap! a1 inc) > > (alter rr + 100) > > (Thread/sleep 8000))) > > (println "Sleeping a bit") > > (Thread/sleep 1000) > > (println "Another dosync") > > (time > > (dosync > > (swap! a2 inc) > > (ref-set rr 1))) > > [@rr @a1 @a2 (.getHistoryCount rr)])) > > > > user> (tz) > > Starting future > > Sleeping a bit > > Another dosync > > "Elapsed time: 7001.554 msecs" > > [1 1 71 0] > > > > Note, how the 71 retries nice fit the approximately 7 seconds left and > the > > 100 miliseconds time-out (LOCK_WAIT_MSECS) for the lock used in > > LockingTransaction.java/tryWriteLock. > > > > Transactions with significantly different run-times should be avoided, > > although there is some point at which older transactions will get their > > turn. This could be another explanation of the effect. Take a look at > the > > barge-function in LockingTransaction.java > > > > Hope this helps, > > Stefan > > -- > You received this message because you are subscribed to the Google > Groups "Clojure" group. > To post to this group, send email to clojure@googlegroups.com > Note that posts from new members are moderated - please be patient with > your first post. > To unsubscribe from this group, send email to > clojure+unsubscr...@googlegroups.com > 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 post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Clojurescript Beginner's Question
Hi! I wonder if someone might tell me what I'm doing wrong here. (ns hello (:require [goog.fx :as fx] [goog.dom :as dom])) (defn ^:export main [] (let [kurdt (dom/getElement "kurdt")] (dom/appendChild (.body (dom/getDocument)) (dom/createDom "h1" 0 (dom/getOuterHtml kurdt))) (fx/Dragger. kurdt) (dom/appendChild (.body (dom/getDocument)) (dom/createDom "h1" 0 (dom/getOuterHtml kurdt) with the HTML: hello.main(); As you can see here http://www2.warwick.ac.uk/fac/cross_fac/comcom/dtcsite/people/students2009/tucker/test2, I am only getting the first output, as if the call to fx/Dragger. is stopping the script. Thank you! Alistair -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Why do transactions block each other?
Congratulations, you've found a bug in clojure 1.3 beta2, see: look with my clojure 1.2.0 version : ;; Clojure 1.2.0 => (def thread (agent "Thread")) (def account (ref 1000)) (send thread (fn [agt aref] (dosync (alter aref + 100) (Thread/sleep 8000) agt)) account) (time (dosync (ref-set account 2000))) #'user/thread #'user/account # "Elapsed time: 0.498106 msecs" 2000 => ;; 10 seconds later : => @account 2100 And now with clojure 1.3 beta1 : ;; Clojure 1.3.0-beta1 => (def thread (agent "Thread")) (def account (ref 1000)) (send thread (fn [agt aref] (dosync (alter aref + 100) (Thread/sleep 8000) agt)) account) (time (dosync (ref-set account 2000))) ;; 10 seconds later : #'user/thread #'user/account # "Elapsed time: 0.270225 msecs" 2000 => @account 2100 And now with Clojure 1.3-beta2 ;; Clojure 1.3.0-beta2 => (def thread (agent "Thread")) (def account (ref 1000)) (send thread (fn [agt aref] (dosync (alter aref + 100) (Thread/sleep 8000) agt)) account) (time (dosync (ref-set account 2000))) #'user/thread #'user/account # "Elapsed time: 7957.328798 msecs" 2000 ;; 10 seconds later : => @account 2000 ;; 10 more seconds later : => @account 2000 2011/8/30 Laurent PETIT > 2011/8/29 Dominikus > >> Thanks a lot for this detailed analysis and the pointers to the Java >> implementation, Stefan! That's excellent and very helpful. >> >> I still wonder, why the first transaction blocks write access. My >> overall understanding of the transaction system is that changes to >> referenced values remain in-transaction before committing them, a >> write-lock shouldn't be needed. I'm surprised, that the second >> transaction is the one who has to retry 71 times even though the first >> transaction hasn't committed anything yet. >> > > I must confess this behaviour also challenges my assumptions. > > Does this work the same whatever the clojure version used ? > > >> >> Cheers, >> >> Dominikus >> >> P.S.: Thanks for the idea to use 'future' to spawn a thread! >> >> On Aug 29, 5:42 pm, Stefan Kamphausen wrote: >> > The call to alter already wrote to the Ref, this requires a write-lock >> on >> > the ref (see LockingTransaction.java/doSet). After that it sleeps a >> while >> > and gets to its commit phase. The other transactions retries in the >> > meantime. Consider the following code, which introduces some atoms for >> > counting the retries >> > >> > (defn tz [] >> > (let [rr (ref 10) >> > a1 (atom 0) >> > a2 (atom 0)] >> > (println "Starting future") >> > (future >> > (dosync >> > (swap! a1 inc) >> > (alter rr + 100) >> > (Thread/sleep 8000))) >> > (println "Sleeping a bit") >> > (Thread/sleep 1000) >> > (println "Another dosync") >> > (time >> > (dosync >> > (swap! a2 inc) >> > (ref-set rr 1))) >> > [@rr @a1 @a2 (.getHistoryCount rr)])) >> > >> > user> (tz) >> > Starting future >> > Sleeping a bit >> > Another dosync >> > "Elapsed time: 7001.554 msecs" >> > [1 1 71 0] >> > >> > Note, how the 71 retries nice fit the approximately 7 seconds left and >> the >> > 100 miliseconds time-out (LOCK_WAIT_MSECS) for the lock used in >> > LockingTransaction.java/tryWriteLock. >> > >> > Transactions with significantly different run-times should be avoided, >> > although there is some point at which older transactions will get their >> > turn. This could be another explanation of the effect. Take a look at >> the >> > barge-function in LockingTransaction.java >> > >> > Hope this helps, >> > Stefan >> >> -- >> You received this message because you are subscribed to the Google >> Groups "Clojure" group. >> To post to this group, send email to clojure@googlegroups.com >> Note that posts from new members are moderated - please be patient with >> your first post. >> To unsubscribe from this group, send email to >> clojure+unsubscr...@googlegroups.com >> 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 post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: JVM 7 support (invokedynamic)
The version of ASM that is bundled in Clojure is very old. This will likely cause problems. You are correct in looking to ASM 4 since it has started supported the JSR-292 stuff and other Java 7 changes. I am planning on doing an extraction, update, and re-packaging of ASM in Clojure as soon as Programming Clojure hits the printers. This most likely won't get started until October though because of conferences. Cheers, Aaron Bedra -- Clojure/core http://clojure.com On 08/29/2011 05:53 PM, Tal Liron wrote: > Progress... is slow. > > I encouraged other people to try, so the least I can do now is to > point you at some of the serious challenges. > > Right now I have what I think is a nice semi-generic mechanism for > invokedynamic. It's called the "Linker": it handles finding the target > method handle, bootstrapping, and what I call "restrapping", which is > what happens when you guard it with an "ILinkable" (another new > interface) and it fallbacks when a SwitchPoint is invalidated. There > some various MethodHandle composing to make sure caller and target are > both happy. I hope the "Linker" will make is easier to add > invokedynamic in Clojure, and possibly in other projects. > > My real challenge is not there, however, but with adapting Clojure to > JVM 7 more generally. invokedynamic requires V1.7 classes, and for > V1.7 the stack frame map that was optional in V1.6 is now a > requirement. This is overall a very good idea for moving the JVM > forward (these maps are a huge help for HotSpot), but I have no doubt > that it will create serious pain for any project that generates JVM > bytecode and until JVM 7 now could afford to be sloppier with stack > frames. The V1.7 verifier will simply not let you load classes that > don't have perfectly aligned maps. > > ASM has very nice support for doing the stack frame arithmetic for > you, but this is still being worked on in ASM 4 (trunk), and is not > working in Clojure. I'm getting VerifyErrors specifically having to do > with the mapping of try-catch blocks, and am working on debugging this > via close look at CheckClassAdapter dumps. It's about as much fun as > filling in tax forms. :/ > > (I've added support for two new defines, -Dclojure.jvm7=true and > -Dclojure.invokedynamic=true, so each can be turned on separately. To > be clear, my problems right now are in -Dclojure.jvm7=true and > -Dclojure.invokedynamic=false.) > > I've already patched one tiny part of ASM commons in order to add > support for invokedynamic, and my work on debugging this may result in > a more major patch to ASM. Assuming I do manage a fix. :/ > > So, what can I say? It's the cutting edge, baby. In for a penny, in > for a pound. > > -Tal > -- > You received this message because you are subscribed to the Google > Groups "Clojure" group. > To post to this group, send email to clojure@googlegroups.com > Note that posts from new members are moderated - please be patient > with your first post. > To unsubscribe from this group, send email to > clojure+unsubscr...@googlegroups.com > 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 post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Why do transactions block each other?
ok so now i'm totally confused, since I cannot see why the behaviour is so different between beta1 and beta 2 ... 2011/8/30 Laurent PETIT > Congratulations, you've found a bug in clojure 1.3 beta2, see: > > look with my clojure 1.2.0 version : > > ;; Clojure 1.2.0 > => (def thread (agent "Thread")) >(def account (ref 1000)) >(send thread > (fn [agt aref] (dosync (alter aref + 100) (Thread/sleep 8000) > agt)) > account) >(time (dosync (ref-set account 2000))) > #'user/thread > #'user/account > # > "Elapsed time: 0.498106 msecs" > 2000 > => ;; 10 seconds later : > => @account > 2100 > > > And now with clojure 1.3 beta1 : > > ;; Clojure 1.3.0-beta1 > => (def thread (agent "Thread")) >(def account (ref 1000)) >(send thread > (fn [agt aref] (dosync (alter aref + 100) (Thread/sleep 8000) > agt)) > account) >(time (dosync (ref-set account 2000))) >;; 10 seconds later : > #'user/thread > #'user/account > # > "Elapsed time: 0.270225 msecs" > 2000 > => @account > 2100 > > And now with Clojure 1.3-beta2 > ;; Clojure 1.3.0-beta2 > => (def thread (agent "Thread")) >(def account (ref 1000)) >(send thread > (fn [agt aref] (dosync (alter aref + 100) (Thread/sleep 8000) > agt)) > account) >(time (dosync (ref-set account 2000))) > #'user/thread > #'user/account > # > "Elapsed time: 7957.328798 msecs" > 2000 >;; 10 seconds later : > => @account > 2000 >;; 10 more seconds later : > => @account > 2000 > > 2011/8/30 Laurent PETIT > >> 2011/8/29 Dominikus >> >>> Thanks a lot for this detailed analysis and the pointers to the Java >>> implementation, Stefan! That's excellent and very helpful. >>> >>> I still wonder, why the first transaction blocks write access. My >>> overall understanding of the transaction system is that changes to >>> referenced values remain in-transaction before committing them, a >>> write-lock shouldn't be needed. I'm surprised, that the second >>> transaction is the one who has to retry 71 times even though the first >>> transaction hasn't committed anything yet. >>> >> >> I must confess this behaviour also challenges my assumptions. >> >> Does this work the same whatever the clojure version used ? >> >> >>> >>> Cheers, >>> >>> Dominikus >>> >>> P.S.: Thanks for the idea to use 'future' to spawn a thread! >>> >>> On Aug 29, 5:42 pm, Stefan Kamphausen wrote: >>> > The call to alter already wrote to the Ref, this requires a write-lock >>> on >>> > the ref (see LockingTransaction.java/doSet). After that it sleeps a >>> while >>> > and gets to its commit phase. The other transactions retries in the >>> > meantime. Consider the following code, which introduces some atoms for >>> > counting the retries >>> > >>> > (defn tz [] >>> > (let [rr (ref 10) >>> > a1 (atom 0) >>> > a2 (atom 0)] >>> > (println "Starting future") >>> > (future >>> > (dosync >>> > (swap! a1 inc) >>> > (alter rr + 100) >>> > (Thread/sleep 8000))) >>> > (println "Sleeping a bit") >>> > (Thread/sleep 1000) >>> > (println "Another dosync") >>> > (time >>> > (dosync >>> > (swap! a2 inc) >>> > (ref-set rr 1))) >>> > [@rr @a1 @a2 (.getHistoryCount rr)])) >>> > >>> > user> (tz) >>> > Starting future >>> > Sleeping a bit >>> > Another dosync >>> > "Elapsed time: 7001.554 msecs" >>> > [1 1 71 0] >>> > >>> > Note, how the 71 retries nice fit the approximately 7 seconds left and >>> the >>> > 100 miliseconds time-out (LOCK_WAIT_MSECS) for the lock used in >>> > LockingTransaction.java/tryWriteLock. >>> > >>> > Transactions with significantly different run-times should be avoided, >>> > although there is some point at which older transactions will get their >>> > turn. This could be another explanation of the effect. Take a look at >>> the >>> > barge-function in LockingTransaction.java >>> > >>> > Hope this helps, >>> > Stefan >>> >>> -- >>> You received this message because you are subscribed to the Google >>> Groups "Clojure" group. >>> To post to this group, send email to clojure@googlegroups.com >>> Note that posts from new members are moderated - please be patient with >>> your first post. >>> To unsubscribe from this group, send email to >>> clojure+unsubscr...@googlegroups.com >>> 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 post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: JVM 7 support (invokedynamic)
On 08/29/2011 06:01 PM, Aaron Bedra wrote: The version of ASM that is bundled in Clojure is very old. This will likely cause problems. You are correct in looking to ASM 4 since it has started supported the JSR-292 stuff and other Java 7 changes. I am planning on doing an extraction, update, and re-packaging of ASM in Clojure as soon as Programming Clojure hits the printers. This most likely won't get started until October though because of conferences. I've already done that for my branch (that was a task in itself! needed a little monkeypatching to support Clojure's DynamicClassLoader), so you may want to leave it to me. My code is in quite a messy state now and I'm embarrassed to make it public quite yet... BTW, does somebody have an Eclipse Java code formatter configuration for Clojure's wacky coding style? -Tal -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: get keys from defrecord
There is no good way to do this in 1.2 other than using the instance mechanism that Aaron suggests. I have had this need myself for several meta-programming type use cases (building specialized record serializers, universal record constructors, etc). We wrap defrecord in our own macros that generate multimethod implementations at record construction time. One possible solution is to use Java reflection to grab the fields directly. Clojure generates some in the class, but I think they all start with an _, so you skip those and probably come up with the correct fields. However, I presume the names would be mangled and you'd need to de-mangle them. I'm not sure if there are any enhancements in the 1.3 record support for this feature. On Aug 29, 11:54 am, Razvan Rotaru wrote: > Hi, > > Assuming I have: > > (defrecord myrecord [:a :b :c]) > > is there a way to get the list of keys from the record definition? > > Thanks, > Razvan -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: get keys from defrecord
On Aug 29, 2011, at 2:57 PM, Tassilo Horn wrote: > > I guess the problem with that is that you need to have an instance of > the record before you can use `keys'. And to create an instance, at > least you have to know the number of keys. > > However, you can inspect the record's constructor using reflection: Or, if structs will do for your application, then you can do this more simply: user=> (defstruct mystruct :a :b :c) #'user/mystruct user=> (keys (struct-map mystruct)) (:a :b :c) -Lee -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: ClojureScript and lein?
> I wanted to give a try to ClojureScript but from Windows XP. > Now I was doing all what is written on github but had to remove -server to > obey "missing jvm.dll" problem (even after coping server path there was > still a problem about loading some routine) After copying the server path, you found another problem about loading some routine. What was the error message? > Now I'm able to compile hello.cljs to hello.js and put reference to > test.html but still it doesn't work. I think that there is some problem with > relative paths. Exactly what commands did you use to compile hello.cljs? The getting started page shows how to do it from both the shell and the REPL, and I suggest trying both. Did you get any error messages at this point? If you open hello.js, do you see something that looks like Javascript? > My final thought is that running it is a nightmare and you wont gain > critical mass to get some feedback from community. It is easy to install and use on Linux, and probably on Mac as well. I was able to install it on Windows 7 using the Windows-Setup instructions. You may be the first to test those instructions on Windows XP. Remember that ClojureScript was only released a month ago, and most of the people contributing to it don't have Windows. That is why these problems can't be solved without feedback from early adopters like yourself. > So the other thought is why can the lein do the job? Has anyone tried? Someone has created a Leiningen-installable ClojureScript compiler, including automatic recompilation when your source code changes. Unfortunately, I haven't been able to make it work on my computer, but you could still give it a try. https://github.com/ibdknox/noir-cljs > I'm > also a Mac user and probably in home all this howto will work, but in > company where we all are using Windows there is no chance to get it > working easily. There are people at your workplace who program in Clojure, or who are willing to try it, but aren't willing to try developing on Linux or Mac? This surprises me. The installation issues will be ironed out eventually. It may be better to use it at home for now, and wait a month or two before recommending it at work. Good luck. -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Why do transactions block each other?
https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/LockingTransaction.java#L424 is definitely the line that causes the write lock to be acquired. I get the same behavior on master(1.3) and 1.2.1: the first time I run the code on a particular ref it locks for writing while the first transaction is running, but subsequent runs do not. 1.3 user=> (def x (ref 0)) #'user/x user=> (time (do (future (dosync (alter x inc) (Thread/sleep 1))) (dosync (alter x dec "Elapsed time: 10007.789 msecs" 0 user=> (time (do (future (dosync (alter x inc) (Thread/sleep 1))) (dosync (alter x dec "Elapsed time: 0.409 msecs" -1 user=> 1.2 Clojure 1.2.1 user=> (def x (ref 0)) #'user/x user=> (time (do (future (dosync (alter x inc) (Thread/sleep 1))) (dosync (alter x dec "Elapsed time: 10007.026 msecs" 0 user=> (time (do (future (dosync (alter x inc) (Thread/sleep 1))) (dosync (alter x dec "Elapsed time: 0.391 msecs" -1 user=> if I had to guess, I'd say that until a ref has some initial number of history entries (1?) to satisfy readers it falls back to locking, but I really have no clue On Mon, Aug 29, 2011 at 4:03 PM, Laurent PETIT wrote: > ok so now i'm totally confused, since I cannot see why the behaviour is so > different between beta1 and beta 2 ... > > 2011/8/30 Laurent PETIT >> >> Congratulations, you've found a bug in clojure 1.3 beta2, see: >> look with my clojure 1.2.0 version : >> ;; Clojure 1.2.0 >> => (def thread (agent "Thread")) >> (def account (ref 1000)) >> (send thread >> (fn [agt aref] (dosync (alter aref + 100) (Thread/sleep 8000) >> agt)) >> account) >> (time (dosync (ref-set account 2000))) >> #'user/thread >> #'user/account >> # >> "Elapsed time: 0.498106 msecs" >> 2000 >> => ;; 10 seconds later : >> => @account >> 2100 >> >> And now with clojure 1.3 beta1 : >> ;; Clojure 1.3.0-beta1 >> => (def thread (agent "Thread")) >> (def account (ref 1000)) >> (send thread >> (fn [agt aref] (dosync (alter aref + 100) (Thread/sleep 8000) >> agt)) >> account) >> (time (dosync (ref-set account 2000))) >> ;; 10 seconds later : >> #'user/thread >> #'user/account >> # >> "Elapsed time: 0.270225 msecs" >> 2000 >> => @account >> 2100 >> And now with Clojure 1.3-beta2 >> ;; Clojure 1.3.0-beta2 >> => (def thread (agent "Thread")) >> (def account (ref 1000)) >> (send thread >> (fn [agt aref] (dosync (alter aref + 100) (Thread/sleep 8000) >> agt)) >> account) >> (time (dosync (ref-set account 2000))) >> #'user/thread >> #'user/account >> # >> "Elapsed time: 7957.328798 msecs" >> 2000 >> ;; 10 seconds later : >> => @account >> 2000 >> ;; 10 more seconds later : >> => @account >> 2000 >> 2011/8/30 Laurent PETIT >>> >>> 2011/8/29 Dominikus Thanks a lot for this detailed analysis and the pointers to the Java implementation, Stefan! That's excellent and very helpful. I still wonder, why the first transaction blocks write access. My overall understanding of the transaction system is that changes to referenced values remain in-transaction before committing them, a write-lock shouldn't be needed. I'm surprised, that the second transaction is the one who has to retry 71 times even though the first transaction hasn't committed anything yet. >>> >>> I must confess this behaviour also challenges my assumptions. >>> Does this work the same whatever the clojure version used ? >>> Cheers, Dominikus P.S.: Thanks for the idea to use 'future' to spawn a thread! On Aug 29, 5:42 pm, Stefan Kamphausen wrote: > The call to alter already wrote to the Ref, this requires a write-lock > on > the ref (see LockingTransaction.java/doSet). After that it sleeps a > while > and gets to its commit phase. The other transactions retries in the > meantime. Consider the following code, which introduces some atoms > for > counting the retries > > (defn tz [] > (let [rr (ref 10) > a1 (atom 0) > a2 (atom 0)] > (println "Starting future") > (future > (dosync > (swap! a1 inc) > (alter rr + 100) > (Thread/sleep 8000))) > (println "Sleeping a bit") > (Thread/sleep 1000) > (println "Another dosync") > (time > (dosync > (swap! a2 inc) > (ref-set rr 1))) > [@rr @a1 @a2 (.getHistoryCount rr)])) > > user> (tz) > Starting future > Sleeping a bit > Another dosync > "Elapsed time: 7001.554 msecs" > [1 1 71 0] > > Note, how the 71 retries nice fit the approximately 7 seconds left and > the > 100 miliseconds time-out (LOCK_WAIT_MSECS) for the lock used in > LockingTransaction.java/tryWriteLock. > > Transactions with significantly different run-times should
Re: Why do transactions block each other?
weird, it actually ping-pongs, every other run of the (time …) the transaction in the future locks the ref writing so you get "Elapsed time: 10006.505 msecs" "Elapsed time: 0.358 msecs" "Elapsed time: 9038.18 msecs" "Elapsed time: 0.348 msecs" "Elapsed time: 26250.854 msecs" On Mon, Aug 29, 2011 at 6:13 PM, Kevin Downey wrote: > https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/LockingTransaction.java#L424 > is definitely the line that causes the write lock to be acquired. > > I get the same behavior on master(1.3) and 1.2.1: > > the first time I run the code on a particular ref it locks for writing > while the first transaction is running, but subsequent runs do not. > > 1.3 > > user=> (def x (ref 0)) > #'user/x > user=> (time (do (future (dosync (alter x inc) (Thread/sleep 1))) > (dosync (alter x dec > "Elapsed time: 10007.789 msecs" > 0 > user=> (time (do (future (dosync (alter x inc) (Thread/sleep 1))) > (dosync (alter x dec > "Elapsed time: 0.409 msecs" > -1 > user=> > > 1.2 > > Clojure 1.2.1 > user=> (def x (ref 0)) > #'user/x > user=> (time (do (future (dosync (alter x inc) (Thread/sleep 1))) > (dosync (alter x dec > "Elapsed time: 10007.026 msecs" > 0 > user=> (time (do (future (dosync (alter x inc) (Thread/sleep 1))) > (dosync (alter x dec > "Elapsed time: 0.391 msecs" > -1 > user=> > > > if I had to guess, I'd say that until a ref has some initial number of > history entries (1?) to satisfy readers it falls back to locking, but > I really have no clue > > On Mon, Aug 29, 2011 at 4:03 PM, Laurent PETIT > wrote: >> ok so now i'm totally confused, since I cannot see why the behaviour is so >> different between beta1 and beta 2 ... >> >> 2011/8/30 Laurent PETIT >>> >>> Congratulations, you've found a bug in clojure 1.3 beta2, see: >>> look with my clojure 1.2.0 version : >>> ;; Clojure 1.2.0 >>> => (def thread (agent "Thread")) >>> (def account (ref 1000)) >>> (send thread >>> (fn [agt aref] (dosync (alter aref + 100) (Thread/sleep 8000) >>> agt)) >>> account) >>> (time (dosync (ref-set account 2000))) >>> #'user/thread >>> #'user/account >>> # >>> "Elapsed time: 0.498106 msecs" >>> 2000 >>> => ;; 10 seconds later : >>> => @account >>> 2100 >>> >>> And now with clojure 1.3 beta1 : >>> ;; Clojure 1.3.0-beta1 >>> => (def thread (agent "Thread")) >>> (def account (ref 1000)) >>> (send thread >>> (fn [agt aref] (dosync (alter aref + 100) (Thread/sleep 8000) >>> agt)) >>> account) >>> (time (dosync (ref-set account 2000))) >>> ;; 10 seconds later : >>> #'user/thread >>> #'user/account >>> # >>> "Elapsed time: 0.270225 msecs" >>> 2000 >>> => @account >>> 2100 >>> And now with Clojure 1.3-beta2 >>> ;; Clojure 1.3.0-beta2 >>> => (def thread (agent "Thread")) >>> (def account (ref 1000)) >>> (send thread >>> (fn [agt aref] (dosync (alter aref + 100) (Thread/sleep 8000) >>> agt)) >>> account) >>> (time (dosync (ref-set account 2000))) >>> #'user/thread >>> #'user/account >>> # >>> "Elapsed time: 7957.328798 msecs" >>> 2000 >>> ;; 10 seconds later : >>> => @account >>> 2000 >>> ;; 10 more seconds later : >>> => @account >>> 2000 >>> 2011/8/30 Laurent PETIT 2011/8/29 Dominikus > > Thanks a lot for this detailed analysis and the pointers to the Java > implementation, Stefan! That's excellent and very helpful. > > I still wonder, why the first transaction blocks write access. My > overall understanding of the transaction system is that changes to > referenced values remain in-transaction before committing them, a > write-lock shouldn't be needed. I'm surprised, that the second > transaction is the one who has to retry 71 times even though the first > transaction hasn't committed anything yet. I must confess this behaviour also challenges my assumptions. Does this work the same whatever the clojure version used ? > > Cheers, > > Dominikus > > P.S.: Thanks for the idea to use 'future' to spawn a thread! > > On Aug 29, 5:42 pm, Stefan Kamphausen wrote: > > The call to alter already wrote to the Ref, this requires a write-lock > > on > > the ref (see LockingTransaction.java/doSet). After that it sleeps a > > while > > and gets to its commit phase. The other transactions retries in the > > meantime. Consider the following code, which introduces some atoms > > for > > counting the retries > > > > (defn tz [] > > (let [rr (ref 10) > > a1 (atom 0) > > a2 (atom 0)] > > (println "Starting future") > > (future > > (dosync > > (swap! a1 inc) > > (alter rr + 100) > > (Thread/sleep 8000))) > > (println "Sleeping a bit") > > (Thread/sleep 1000) > > (println "Another dosync") > > (time > > (dosync > > (swap
Re: get keys from defrecord
On Aug 29, 2011, at 8:20 PM, Alex Miller wrote: > I'm not sure if there are any enhancements in the 1.3 record support > for this feature. In 1.3beta2, the record class has a static method getBasis that will give you the fields. I remember Fogus mentioning this on the mailing list. The design notes [1] say "These methods should not be used in Clojure code" as they're intended for tool support, but they seem generally useful to me. user=> (clojure-version) "1.3.0-beta2" user=> (defrecord MyRecord [a b]) user.MyRecord user=> (MyRecord/getBasis) [a b] [1] http://dev.clojure.org/display/design/defrecord+improvements Steve Miner -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Clojurescript Beginner's Question
Firebug says goog.fx.Dragger is not a constructor. Firebug's error message doesn't match my understanding of the goog.fx.Dragger documentation, but yes, that line did stop the script. http://closure-library.googlecode.com/svn/docs/class_goog_fx_Dragger.html On Mon, Aug 29, 2011 at 6:50 PM, atucker wrote: > Hi! I wonder if someone might tell me what I'm doing wrong here. > > (ns hello (:require [goog.fx :as fx] [goog.dom :as dom])) > > (defn ^:export main [] > (let [kurdt (dom/getElement "kurdt")] > (dom/appendChild (.body (dom/getDocument)) (dom/createDom "h1" 0 > (dom/getOuterHtml kurdt))) > (fx/Dragger. kurdt) > (dom/appendChild (.body (dom/getDocument)) (dom/createDom "h1" 0 > (dom/getOuterHtml kurdt) > > with the HTML: > > > > > > > > hello.main(); > > > > > As you can see here > http://www2.warwick.ac.uk/fac/cross_fac/comcom/dtcsite/people/students2009/tucker/test2, > I am only getting the first output, as if the call to fx/Dragger. is > stopping the script. > > Thank you! Alistair > > -- > You received this message because you are subscribed to the Google > Groups "Clojure" group. > To post to this group, send email to clojure@googlegroups.com > Note that posts from new members are moderated - please be patient with your > first post. > To unsubscribe from this group, send email to > clojure+unsubscr...@googlegroups.com > 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 post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Why do transactions block each other?
https://github.com/hiredman/clojure/compare/master...apocrypha-stm#L0L296 I've been playing around with the stm, and I think this change gives you the behavior that is intuitively expected, someone else will have to speak for correctness. ant test runs successfully but I don't know how extensive the stm tests are. I think the ping ponging arises because both transactions race to acquire the write lock. Seems odd to me that it would ping pong so regularly, but it is a concurrent program, so who knows. Having the first writer lock may be an attempt to ensure that at least one transaction can complete without retries. On Mon, Aug 29, 2011 at 6:42 PM, Kevin Downey wrote: > weird, it actually ping-pongs, every other run of the (time …) the > transaction in the future locks the ref writing so you get > > "Elapsed time: 10006.505 msecs" > "Elapsed time: 0.358 msecs" > "Elapsed time: 9038.18 msecs" > "Elapsed time: 0.348 msecs" > "Elapsed time: 26250.854 msecs" > > On Mon, Aug 29, 2011 at 6:13 PM, Kevin Downey wrote: >> https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/LockingTransaction.java#L424 >> is definitely the line that causes the write lock to be acquired. >> >> I get the same behavior on master(1.3) and 1.2.1: >> >> the first time I run the code on a particular ref it locks for writing >> while the first transaction is running, but subsequent runs do not. >> >> 1.3 >> >> user=> (def x (ref 0)) >> #'user/x >> user=> (time (do (future (dosync (alter x inc) (Thread/sleep 1))) >> (dosync (alter x dec >> "Elapsed time: 10007.789 msecs" >> 0 >> user=> (time (do (future (dosync (alter x inc) (Thread/sleep 1))) >> (dosync (alter x dec >> "Elapsed time: 0.409 msecs" >> -1 >> user=> >> >> 1.2 >> >> Clojure 1.2.1 >> user=> (def x (ref 0)) >> #'user/x >> user=> (time (do (future (dosync (alter x inc) (Thread/sleep 1))) >> (dosync (alter x dec >> "Elapsed time: 10007.026 msecs" >> 0 >> user=> (time (do (future (dosync (alter x inc) (Thread/sleep 1))) >> (dosync (alter x dec >> "Elapsed time: 0.391 msecs" >> -1 >> user=> >> >> >> if I had to guess, I'd say that until a ref has some initial number of >> history entries (1?) to satisfy readers it falls back to locking, but >> I really have no clue >> >> On Mon, Aug 29, 2011 at 4:03 PM, Laurent PETIT >> wrote: >>> ok so now i'm totally confused, since I cannot see why the behaviour is so >>> different between beta1 and beta 2 ... >>> >>> 2011/8/30 Laurent PETIT Congratulations, you've found a bug in clojure 1.3 beta2, see: look with my clojure 1.2.0 version : ;; Clojure 1.2.0 => (def thread (agent "Thread")) (def account (ref 1000)) (send thread (fn [agt aref] (dosync (alter aref + 100) (Thread/sleep 8000) agt)) account) (time (dosync (ref-set account 2000))) #'user/thread #'user/account # "Elapsed time: 0.498106 msecs" 2000 => ;; 10 seconds later : => @account 2100 And now with clojure 1.3 beta1 : ;; Clojure 1.3.0-beta1 => (def thread (agent "Thread")) (def account (ref 1000)) (send thread (fn [agt aref] (dosync (alter aref + 100) (Thread/sleep 8000) agt)) account) (time (dosync (ref-set account 2000))) ;; 10 seconds later : #'user/thread #'user/account # "Elapsed time: 0.270225 msecs" 2000 => @account 2100 And now with Clojure 1.3-beta2 ;; Clojure 1.3.0-beta2 => (def thread (agent "Thread")) (def account (ref 1000)) (send thread (fn [agt aref] (dosync (alter aref + 100) (Thread/sleep 8000) agt)) account) (time (dosync (ref-set account 2000))) #'user/thread #'user/account # "Elapsed time: 7957.328798 msecs" 2000 ;; 10 seconds later : => @account 2000 ;; 10 more seconds later : => @account 2000 2011/8/30 Laurent PETIT > > 2011/8/29 Dominikus >> >> Thanks a lot for this detailed analysis and the pointers to the Java >> implementation, Stefan! That's excellent and very helpful. >> >> I still wonder, why the first transaction blocks write access. My >> overall understanding of the transaction system is that changes to >> referenced values remain in-transaction before committing them, a >> write-lock shouldn't be needed. I'm surprised, that the second >> transaction is the one who has to retry 71 times even though the first >> transaction hasn't committed anything yet. > > I must confess this behaviour also challenges my assumptions. > Does this work the same whatever the clojure version used ? > >> >> Cheers, >> >> Dominikus >> >> P.S.: Thanks for the idea to use 'future' to spawn a thread! >> >> On Aug 29, 5:42 pm, Stefan Kamphausen wrote:
Re: Clojure 1.3 Beta 2
The change to beta2 isn't working for me: org.clojure clojure 1.3.0-beta2 1.3.0-beta1 works fine. On Aug 29, 7:28 am, Christopher Redinger wrote: > Clojure 1.3 Beta 2 is now available at > > http://clojure.org/downloads > > The list of changes: > > * clojure.test/*/*-report vars made dynamic for use with external > tools. > * Calls favor arg vectors :tag over var :tag (CLJ-811) > * BigInt ops made faster when values are small enough to be treated as > longs > * rational? metadata fixed > * partition and partition-all holds less > * Bug fixed on transient vectors > * print-dup and print-method removed for deftypes (CLJ-812) > * Prevent make-parents NPE, (CLJ-808) > * Special print support removed for BigIntegers. (CLJ-798) > > Please grab it and let us know how it works for you. > > Thanks! > > -- > Chris Redinger > Clojure/corehttp://clojure.com -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Reify creates two objects?
I came across the following behavior today, and wanted to make sure it's expected (on 1.2 and 1.3-beta2). Each time a reify form is executed, two fresh objects seem to be created; one is immediately thrown away, and the other is returned from the form: user=> (defn foo [] (let [x (reify Object (finalize [this] (println "Finalize" this)))] (println "Create" x) x)) user=> (def x [(foo) (foo)]) Create # Create # user=> (System/gc) Finalize # Finalize # user=> (def x nil) user=> (System/gc) Finalize # Finalize # Thanks, Jason -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: ClojureScript Compile errors
On Wed, Aug 10, 2011 at 7:39 AM, Rich Hickey wrote: > :use … :only doesn't have the problems of full :use. > > Enhancement ticket and patch for :use … :only welcome. Note it must support > :use … :only only, i.e. :only is required. > > Rich http://dev.clojure.org/jira/browse/CLJS-65. Hopefully this is an ok approach. Also couldn't find any tests related to namespace declaration parsing so I didn't add any. David -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Clojure 1.3 Beta 2
False alarm. Some trouble with the VPN line. On Aug 29, 9:06 pm, Armando Blancas wrote: > The change to beta2 isn't working for me: > > > org.clojure > clojure > 1.3.0-beta2 > > > 1.3.0-beta1 works fine. > > On Aug 29, 7:28 am, Christopher Redinger wrote: > > > > > > > > > Clojure 1.3 Beta 2 is now available at > > >http://clojure.org/downloads > > > The list of changes: > > > * clojure.test/*/*-report vars made dynamic for use with external > > tools. > > * Calls favor arg vectors :tag over var :tag (CLJ-811) > > * BigInt ops made faster when values are small enough to be treated as > > longs > > * rational? metadata fixed > > * partition and partition-all holds less > > * Bug fixed on transient vectors > > * print-dup and print-method removed for deftypes (CLJ-812) > > * Prevent make-parents NPE, (CLJ-808) > > * Special print support removed for BigIntegers. (CLJ-798) > > > Please grab it and let us know how it works for you. > > > Thanks! > > > -- > > Chris Redinger > > Clojure/corehttp://clojure.com -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Clojure 1.3 Beta 2
Not surprisingly, some of the benchmarks game programs written for Clojure 1.2 have problems with 1.3 Beta 2. My guess is that small changes to the programs will be required to catch up with the new version, but occasionally program failures have indicated a bug in new versions of other languages. Mon 15:17:15 ...OK .binarytrees.clojure-5.clojure [33] Mon 15:21:02 ...OK .binarytrees.clojure-4.clojure [32] Mon 15:30:04 ...OK .binarytrees.clojure [31] Mon 15:37:59 ...OK .binarytrees.clojure-2.clojure [30] Mon 15:49:27 ...OK .binarytrees.clojure-3.clojure [29] Mon 15:54:51 ...OK fannkuchredux.clojure-2.clojure [28] Mon 15:58:54 ...OK .fasta.clojure-2.clojure [27] Mon 16:00:21 ...OK .fasta.clojure [26] Mon 16:02:01 .PROGRAM FAILED fasta.clojure-4.clojure [25] Mon 16:02:04 .PROGRAM FAILED fasta.clojure-3.clojure [24] Mon 16:02:07 .PROGRAM FAILED fastaredux.clojure-4.clojure [23] Mon 16:02:10 .PROGRAM FAILED knucleotide.clojure-3.clojure [22] Mon 16:02:12 ...OK knucleotide.clojure-2.clojure [21] Mon 16:10:07 ...OK knucleotide.clojure [20] Mon 16:21:06 ...OK .mandelbrot.clojure [19] Mon 16:29:08 .PROGRAM FAILED mandelbrot.clojure-3.clojure [18] Mon 16:29:11 .PROGRAM FAILED mandelbrot.clojure-4.clojure [17] Mon 16:29:14 ...OK .mandelbrot.clojure-2.clojure [16] Mon 16:37:06 .PROGRAM FAILED meteor.clojure [15] Mon 16:37:12 ...TIMED OUT nbody.clojure-2.clojure [14] Mon 17:47:43 .PROGRAM FAILED pidigits.clojure [13] Mon 17:47:46 ...OK .regexdna.clojure-3.clojure [12] Mon 17:52:45 .PROGRAM FAILED regexdna.clojure-2.clojure [11] Mon 17:52:47 ...PROGRAM FAILED .revcomp.clojure [10] Mon 17:53:38 ...PROGRAM FAILED .revcomp.clojure-2.clojure [9] Mon 18:03:45 ...OK .revcomp.clojure-4.clojure [8] Mon 18:04:31 ...OK .revcomp.clojure-3.clojure [7] Mon 18:05:07 ...OK .spectralnorm.clojure-5.clojure [6] Mon 18:09:07 ...OK .spectralnorm.clojure-7.clojure [5] Mon 18:11:06 ...OK .spectralnorm.clojure-2.clojure [4] Mon 18:16:31 ...OK .spectralnorm.clojure-6.clojure [3] Mon 18:18:28 ...TIMED OUT .threadring.clojure [2] Mon 19:21:30 ...TIMED OUT .threadring.clojure-2.clojure [1] (Note reverse-complement and reverse-complement #2 fail because memory settings were requested to show reduced Clojure memory usage on the other reverse-complement programs.) The program source code, with build and run logs can be reached from the program name links - http://shootout.alioth.debian.org/u64/measurements.php?lang=clojure -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Why do transactions block each other?
My tests were false. Since I sent the code "at once" to the REPL, there was a race condition between the start of the agent and the dosync for setting the ref's value to 2000 ; this explains the weirdness of my test results (thank you, Mr Murphy, for having made the tests look like beta2 behaved differently from the others ...) So now I see consistent behaviours across 1.2.0, beta1 and beta2. But I am still perplex and confused by the behaviour ... 2011/8/30 Laurent PETIT > ok so now i'm totally confused, since I cannot see why the behaviour is so > different between beta1 and beta 2 ... > > > 2011/8/30 Laurent PETIT > >> Congratulations, you've found a bug in clojure 1.3 beta2, see: >> >> look with my clojure 1.2.0 version : >> >> ;; Clojure 1.2.0 >> => (def thread (agent "Thread")) >>(def account (ref 1000)) >>(send thread >> (fn [agt aref] (dosync (alter aref + 100) (Thread/sleep 8000) >> agt)) >> account) >>(time (dosync (ref-set account 2000))) >> #'user/thread >> #'user/account >> # >> "Elapsed time: 0.498106 msecs" >> 2000 >> => ;; 10 seconds later : >> => @account >> 2100 >> >> >> And now with clojure 1.3 beta1 : >> >> ;; Clojure 1.3.0-beta1 >> => (def thread (agent "Thread")) >>(def account (ref 1000)) >>(send thread >> (fn [agt aref] (dosync (alter aref + 100) (Thread/sleep 8000) >> agt)) >> account) >>(time (dosync (ref-set account 2000))) >>;; 10 seconds later : >> #'user/thread >> #'user/account >> # >> "Elapsed time: 0.270225 msecs" >> 2000 >> => @account >> 2100 >> >> And now with Clojure 1.3-beta2 >> ;; Clojure 1.3.0-beta2 >> => (def thread (agent "Thread")) >>(def account (ref 1000)) >>(send thread >> (fn [agt aref] (dosync (alter aref + 100) (Thread/sleep 8000) >> agt)) >> account) >>(time (dosync (ref-set account 2000))) >> #'user/thread >> #'user/account >> # >> "Elapsed time: 7957.328798 msecs" >> 2000 >>;; 10 seconds later : >> => @account >> 2000 >>;; 10 more seconds later : >> => @account >> 2000 >> >> 2011/8/30 Laurent PETIT >> >>> 2011/8/29 Dominikus >>> Thanks a lot for this detailed analysis and the pointers to the Java implementation, Stefan! That's excellent and very helpful. I still wonder, why the first transaction blocks write access. My overall understanding of the transaction system is that changes to referenced values remain in-transaction before committing them, a write-lock shouldn't be needed. I'm surprised, that the second transaction is the one who has to retry 71 times even though the first transaction hasn't committed anything yet. >>> >>> I must confess this behaviour also challenges my assumptions. >>> >>> Does this work the same whatever the clojure version used ? >>> >>> Cheers, Dominikus P.S.: Thanks for the idea to use 'future' to spawn a thread! On Aug 29, 5:42 pm, Stefan Kamphausen wrote: > The call to alter already wrote to the Ref, this requires a write-lock on > the ref (see LockingTransaction.java/doSet). After that it sleeps a while > and gets to its commit phase. The other transactions retries in the > meantime. Consider the following code, which introduces some atoms for > counting the retries > > (defn tz [] > (let [rr (ref 10) > a1 (atom 0) > a2 (atom 0)] > (println "Starting future") > (future > (dosync > (swap! a1 inc) > (alter rr + 100) > (Thread/sleep 8000))) > (println "Sleeping a bit") > (Thread/sleep 1000) > (println "Another dosync") > (time > (dosync > (swap! a2 inc) > (ref-set rr 1))) > [@rr @a1 @a2 (.getHistoryCount rr)])) > > user> (tz) > Starting future > Sleeping a bit > Another dosync > "Elapsed time: 7001.554 msecs" > [1 1 71 0] > > Note, how the 71 retries nice fit the approximately 7 seconds left and the > 100 miliseconds time-out (LOCK_WAIT_MSECS) for the lock used in > LockingTransaction.java/tryWriteLock. > > Transactions with significantly different run-times should be avoided, > although there is some point at which older transactions will get their > turn. This could be another explanation of the effect. Take a look at the > barge-function in LockingTransaction.java > > Hope this helps, > Stefan -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit thi
Re: Why do transactions block each other?
the two threads race to acquire the write lock and the winner runs, the loser retries. my guess is acquiring the write lock helps avoid live locks between transactions. On Mon, Aug 29, 2011 at 10:59 PM, Laurent PETIT wrote: > My tests were false. > Since I sent the code "at once" to the REPL, there was a race condition > between the start of the agent and the dosync for setting the ref's value to > 2000 ; this explains the weirdness of my test results (thank you, Mr Murphy, > for having made the tests look like beta2 behaved differently from the > others ...) > So now I see consistent behaviours across 1.2.0, beta1 and beta2. > But I am still perplex and confused by the behaviour ... > > 2011/8/30 Laurent PETIT >> >> ok so now i'm totally confused, since I cannot see why the behaviour is so >> different between beta1 and beta 2 ... >> >> 2011/8/30 Laurent PETIT >>> >>> Congratulations, you've found a bug in clojure 1.3 beta2, see: >>> look with my clojure 1.2.0 version : >>> ;; Clojure 1.2.0 >>> => (def thread (agent "Thread")) >>> (def account (ref 1000)) >>> (send thread >>> (fn [agt aref] (dosync (alter aref + 100) (Thread/sleep 8000) >>> agt)) >>> account) >>> (time (dosync (ref-set account 2000))) >>> #'user/thread >>> #'user/account >>> # >>> "Elapsed time: 0.498106 msecs" >>> 2000 >>> => ;; 10 seconds later : >>> => @account >>> 2100 >>> >>> And now with clojure 1.3 beta1 : >>> ;; Clojure 1.3.0-beta1 >>> => (def thread (agent "Thread")) >>> (def account (ref 1000)) >>> (send thread >>> (fn [agt aref] (dosync (alter aref + 100) (Thread/sleep 8000) >>> agt)) >>> account) >>> (time (dosync (ref-set account 2000))) >>> ;; 10 seconds later : >>> #'user/thread >>> #'user/account >>> # >>> "Elapsed time: 0.270225 msecs" >>> 2000 >>> => @account >>> 2100 >>> And now with Clojure 1.3-beta2 >>> ;; Clojure 1.3.0-beta2 >>> => (def thread (agent "Thread")) >>> (def account (ref 1000)) >>> (send thread >>> (fn [agt aref] (dosync (alter aref + 100) (Thread/sleep 8000) >>> agt)) >>> account) >>> (time (dosync (ref-set account 2000))) >>> #'user/thread >>> #'user/account >>> # >>> "Elapsed time: 7957.328798 msecs" >>> 2000 >>> ;; 10 seconds later : >>> => @account >>> 2000 >>> ;; 10 more seconds later : >>> => @account >>> 2000 >>> 2011/8/30 Laurent PETIT 2011/8/29 Dominikus > > Thanks a lot for this detailed analysis and the pointers to the Java > implementation, Stefan! That's excellent and very helpful. > > I still wonder, why the first transaction blocks write access. My > overall understanding of the transaction system is that changes to > referenced values remain in-transaction before committing them, a > write-lock shouldn't be needed. I'm surprised, that the second > transaction is the one who has to retry 71 times even though the first > transaction hasn't committed anything yet. I must confess this behaviour also challenges my assumptions. Does this work the same whatever the clojure version used ? > > Cheers, > > Dominikus > > P.S.: Thanks for the idea to use 'future' to spawn a thread! > > On Aug 29, 5:42 pm, Stefan Kamphausen wrote: > > The call to alter already wrote to the Ref, this requires a > > write-lock on > > the ref (see LockingTransaction.java/doSet). After that it sleeps a > > while > > and gets to its commit phase. The other transactions retries in the > > meantime. Consider the following code, which introduces some atoms > > for > > counting the retries > > > > (defn tz [] > > (let [rr (ref 10) > > a1 (atom 0) > > a2 (atom 0)] > > (println "Starting future") > > (future > > (dosync > > (swap! a1 inc) > > (alter rr + 100) > > (Thread/sleep 8000))) > > (println "Sleeping a bit") > > (Thread/sleep 1000) > > (println "Another dosync") > > (time > > (dosync > > (swap! a2 inc) > > (ref-set rr 1))) > > [@rr @a1 @a2 (.getHistoryCount rr)])) > > > > user> (tz) > > Starting future > > Sleeping a bit > > Another dosync > > "Elapsed time: 7001.554 msecs" > > [1 1 71 0] > > > > Note, how the 71 retries nice fit the approximately 7 seconds left > > and the > > 100 miliseconds time-out (LOCK_WAIT_MSECS) for the lock used in > > LockingTransaction.java/tryWriteLock. > > > > Transactions with significantly different run-times should be > > avoided, > > although there is some point at which older transactions will get > > their > > turn. This could be another explanation of the effect. Take a look > > at the > > barge-function in LockingTransaction.java > > > > Hope this helps, > > Stefan > > -- > You received thi