Thanks Alex! Now that I took a second look at Daniel's code, it seems assoc! is used like swap!, as if it would modify m in place. So I would expect, if it runs without errors, result to be {:a 0}.
Given that transients are values (not reference types like ref or atom) I can't think of a case where they can be modified concurrently. On Tue, Nov 4, 2014 at 11:19 AM, Alex Miller <a...@puredanger.com> wrote: > > > On Monday, November 3, 2014 9:00:10 PM UTC-6, Atamert Ölçgen wrote: >> >> >> >> On Mon, Nov 3, 2014 at 5:57 PM, Daniel Marjenburgh <dmarje...@gmail.com> >> wrote: >> >>> Hi, >>> >>> I just want to address this issue (CLJ-1498 >>> <http://dev.clojure.org/jira/browse/CLJ-1498>). It was accepted in >>> 1.7-alpha2 and I haven't seen a lot of discussion around it, even though >>> it's quite a big change. >>> >>> With this change the following code is possible: >>> >> >> With persistents the result would be the same, every time. If this is now >> valid Clojure, I didn't run it myself, we are sacrificing consistency. I >> don't understand what we're getting in return. >> >> Even the simple example in the ticket (with one future) doesn't make a >> lot of sense to me. >> >> Am I missing something obvious? >> > > Transients always expect thread isolation. In the past this was locked to > a single thread (the one that made the transient). That restriction now > extends to being used by multiple threads, but isolation should still be > maintained for proper use. > > What we are gaining is the ability to use transient collections in go > blocks with core.async, where the thread being used is just one pool out of > a thread. For example (just typing this not running it, so excuse any > typos): > > (defn drain [ch coll] > (let [t (transient []] > (go-loop > (if-some [v (<! ch)] > (do (conj! t v) (recur)) > (persistent! t))))) > > This doesn't necessarily work in core.async because each time the <! > parks, it may be woken up with a different thread from the pool. The > transient change allows this kind of code to succeed. > > >> >>> (let [m (transient {:a 0}) >>> futs (for [n (range 100)] >>> (future (assoc! m :a (inc (:a m)))))] >>> (mapv deref futs) ; wait until futures are done >>> (persistent! m)) >>> >>> >>> The results will vary per run, where it used to throw >>> an IllegalAccessError: "Transient used by non-owner thread". >>> >>> I understand the problems of not being able to have 1 go routine access >>> a transient, even though it would be safe, but this solution feels like >>> it's throwing out the baby with the bathwater. Basically, it's doing away >>> with what the following block on clojure.org >>> <http://clojure.org/transients> says: >>> >>> *Transients enforce thread isolation**.* Because each result of a >>>> transient operation shares (mutable) structure with the previous, it would >>>> be very dangerous if more than one thread were to manipulate a transient at >>>> once. In order to prevent this, transients will detect any (read or write) >>>> use from a thread other than the one that created them and throw an >>>> exception. >>> >>> >>> >>>> >>>> This may not sound like a concurrency story, but single-thread >>>> isolation is actually a very useful concurrency semantic. The whole point >>>> of using transients is that doing so is safe, because their use is an >>>> isolated implementation detail of otherwise functional code. Having that be >>>> enforced means that some things that would normally be very hard to make >>>> safe with ordinary mutable data structures become easy. >>> >>> >>> I don't have a good solution for dealing with transients and logical >>> threads, but I would much prefer keeping the semantics of transients as >>> they are and maybe pass an option to transient to disable owner checking. >>> >>> -- >>> You received this message because you are subscribed to the Google >>> Groups "Clojure" group. >>> To post to this group, send email to clo...@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+u...@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 unsubscribe from this group and stop receiving emails from it, send >>> an email to clojure+u...@googlegroups.com. >>> For more options, visit https://groups.google.com/d/optout. >>> >> >> >> >> -- >> Kind Regards, >> Atamert Ölçgen >> >> -+- >> --+ >> +++ >> >> www.muhuk.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 > --- > You received this message because you are subscribed to the Google Groups > "Clojure" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to clojure+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout. > -- Kind Regards, Atamert Ölçgen -+- --+ +++ www.muhuk.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 --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.