Re: About transients no longer being safe in 1.7-alpha2

2015-06-09 Thread Alex Miller
Yes

-- 
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.


Re: About transients no longer being safe in 1.7-alpha2

2015-06-08 Thread Ryan Schmitt
Will someone remember to update http://clojure.org/transients once 1.7.0 is 
released?

On Monday, November 3, 2014 at 1:57:58 AM UTC-8, Daniel Marjenburgh 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:

 (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 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.


Re: About transients no longer being safe in 1.7-alpha2

2014-11-05 Thread Daniel Marjenburgh
Hi Atamert, yes, that is also wrong usage that is not caught. I do want to 
focus on the current change though.

So the thought behind this change is that the birth-thread check was 
unnecessary or too strict from the beginning and people should just use 
transients correctly, caveat implementor. No more kids gloves.

There is a paragraph http://clojure.org/transients dedicated to 
enforcement of thread-isolation, which I think is great. I also understand 
we want to give programmers more flexibility in using transients in other 
(mutlithreaded) contexts where the user knows it will be safe. I just think 
throwing away the entire safeguard is overkill and it's making unsafe 
Clojure code not only really easy, but even the default in the case of 
transients. All programs not using core.async could benefit from the 
owner-check.

Again, like Alex suggested, a flag like (transient m {} :thread-isolated? 
false) or something (with the default to true) would at least ease my mind 
a bit. It would also alert programmers in core async when they see it, that 
they need to make sure only one logical thread should have access.


 But they would run fine, if you used delay's instead of future's. Same 
 wrong usage, single threaded. So the issue is not really this new change.

 (See my code with delay's earlier) 

  

-- 
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.


Re: About transients no longer being safe in 1.7-alpha2

2014-11-04 Thread Daniel Marjenburgh
I'll be more careful before posted code that doesn't compile :)
Anyway,  here's my output using clojure 1.7-alpha3

https://lh4.googleusercontent.com/-MqiKnTcxneE/VFigwvQtzBI/A08/vGvY2waCJdc/s1600/Screen%2BShot%2B2014-11-04%2Bat%2B10.43.17.png
It could be that depending on OS/env the second future starts after the 
first one finishes (if you add more futures or Thread sleeps it might be 
easier to reproduce).
But this example already shows that 2 threads are mutating the same 
transient, otherwise, as Atamert pointed out, the result should have been 
45.

Op dinsdag 4 november 2014 08:45:37 UTC+1 schreef Sean Corfield:

 On Nov 3, 2014, at 11:13 PM, Daniel Marjenburgh dmarje...@gmail.com 
 javascript: wrote: 
  I was a bit too quick there and posted some errors int he code: 

 That’s still not quite right. I think you mean: 

 (let [v (transient {:a 0}) 
   f1 (future (reduce #(assoc! % :a (+ (:a %) %2)) v (range 10))) 
   f2 (future (reduce #(assoc! % :a (+ (:a %) %2)) v (range 10)))] 
   @f1 @f2 ; wait for futures 
   (persistent! @f1)) 

 Which seems to consistently produce {:a 90} on both Clojure 1.7.0 Alpha 2 
 and Clojure 1.7.0 Alpha 3. 

 Sean Corfield -- (904) 302-SEAN 
 An Architect's View -- http://corfield.org/ 

 Perfection is the enemy of the good. 
 -- Gustave Flaubert, French realist novelist (1821-1880) 





-- 
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.


Re: About transients no longer being safe in 1.7-alpha2

2014-11-04 Thread Jean Niklas L'orange
Hi there,

On Tuesday, November 4, 2014 8:05:03 AM UTC+1, Daniel Marjenburgh wrote:

 I know transients aren't bash-in-place, as they may return new references, 
 but that is not the problem I'm having here.
 If you bash in place, you would get unexpected results, but still the same 
 result every time. The problem here is that the 'value' of the transient is 
 changing underneath you because of another thread.


To ensure consistency, you must ensure that you update a transient value at 
most once – all calls (including reads) on the same transient value after 
an update is illegal/undefined behaviour. Transient updates – minus 
persistent! – will always return a new transient value, even though the 
transient returned may be the same reference. So the code

(let [v (transient {:a 0})
  f1 (future (reduce #(assoc! % (+ (:a %) %2)) v (range 10)))
  f2 (future (reduce #(assoc! % (+ (:a %) %2)) v (range 10)))]
  @f1 @f2 ; wait for futures
  (persistent! @f1))

will result in undefined behaviour, because the original v is updated twice 
(and is potentially read after an update). The correct way would be to do 
the following:

(let [v {:a 0}
  f1 (future (reduce #(assoc! % (+ (:a %) %2)) (transient v) (range 
10)))
  f2 (future (reduce #(assoc! % (+ (:a %) %2)) (transient v) (range 
10)))]
  @f1 @f2 ; wait for futures
  (persistent! @f1))

I don't see an explicit rule at http://clojure.org/transients stating this, 
although I feel it is implicit from the bash in-place rule. Perhaps that's 
something worth adding to the page to avoid confusion.

--
Regards,
Jean Niklas L'orange

 

 Op dinsdag 4 november 2014 06:13:00 UTC+1 schreef Alex Miller:



 On Monday, November 3, 2014 10:44:19 PM UTC-6, Atamert Ölçgen wrote:

 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}.


 Right, that is an incorrect usage - it will actually modify with changes 
 though, but not in expected ways (this is independent of the change we're 
 discussing - you can get the same behavior in a single thread modifying a 
 transient without reusing the return).

 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.


 You can, but not without going pretty far out of normal Clojure code. 
  



 On Tue, Nov 4, 2014 at 11:19 AM, Alex Miller al...@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 

Re: About transients no longer being safe in 1.7-alpha2

2014-11-04 Thread Daniel Marjenburgh
Hi Jean,

In this case, we are dealing with 1 key-value pair, so there is only one 
transient reference all the time. It is not my experience that each update 
returns a new transient value (here, each update is identical to the 
original, as per the identical? predicate).

I know you shouldn't use transients in the way I illustrated, but use it as 
if it always returns a new value. In that scenario, you would not get 
inconsistent results, as multiple threads would have to coordinate to pass 
the reference around (as happens in core.async) and the birth-thread check 
is unnecessary.

Still, the onus is now put on the user to ensure correct use of transients 
in a multi-threaded environment, as no warning or error is given anymore. 
It has always been the case that Clojure makes it hard to write unsafe 
mutable code, you had to go out of your way. With this change, I feel we 
are giving up this safeguard a bit too easily.

Maybe another solution could be to have the birth-thread explicitly 
relinquish ownership of the transient, for example, by calling 
(relinquish-transient m). Then the thread that makes the next transient 
update would become the new owner. If another thread updates a transient 
while another threads owns it, the usual error is thrown. This way we 
maintain the safety as before and it becomes a issue for core.async to deal 
with transients in logical threads, not clojure.core. I guess a go macro 
could recognize transients in go-blocks and auto-relinguish them before 
parking operations so that the user can keep thinking in logical threads. 
I'd like to know how feasible a solution like that would be.

Op dinsdag 4 november 2014 11:12:08 UTC+1 schreef Jean Niklas L'orange:

 Hi there,

 On Tuesday, November 4, 2014 8:05:03 AM UTC+1, Daniel Marjenburgh wrote:

 I know transients aren't bash-in-place, as they may return new 
 references, but that is not the problem I'm having here.
 If you bash in place, you would get unexpected results, but still the 
 same result every time. The problem here is that the 'value' of the 
 transient is changing underneath you because of another thread.


 To ensure consistency, you must ensure that you update a transient value 
 at most once – all calls (including reads) on the same transient value 
 after an update is illegal/undefined behaviour. Transient updates – minus 
 persistent! – will always return a new transient value, even though the 
 transient returned may be the same reference. So the code

 (let [v (transient {:a 0})
   f1 (future (reduce #(assoc! % (+ (:a %) %2)) v (range 10)))
   f2 (future (reduce #(assoc! % (+ (:a %) %2)) v (range 10)))]
   @f1 @f2 ; wait for futures
   (persistent! @f1))

 will result in undefined behaviour, because the original v is updated 
 twice (and is potentially read after an update). The correct way would be 
 to do the following:

 (let [v {:a 0}
   f1 (future (reduce #(assoc! % (+ (:a %) %2)) (transient v) (range 
 10)))
   f2 (future (reduce #(assoc! % (+ (:a %) %2)) (transient v) (range 
 10)))]
   @f1 @f2 ; wait for futures
   (persistent! @f1))

 I don't see an explicit rule at http://clojure.org/transients stating 
 this, although I feel it is implicit from the bash in-place rule. Perhaps 
 that's something worth adding to the page to avoid confusion.

 --
 Regards,
 Jean Niklas L'orange

  

 Op dinsdag 4 november 2014 06:13:00 UTC+1 schreef Alex Miller:



 On Monday, November 3, 2014 10:44:19 PM UTC-6, Atamert Ölçgen wrote:

 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}.


 Right, that is an incorrect usage - it will actually modify with changes 
 though, but not in expected ways (this is independent of the change we're 
 discussing - you can get the same behavior in a single thread modifying a 
 transient without reusing the return).

 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.


 You can, but not without going pretty far out of normal Clojure code. 
  



 On Tue, Nov 4, 2014 at 11:19 AM, Alex Miller al...@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 

Re: About transients no longer being safe in 1.7-alpha2

2014-11-04 Thread Jean Niklas L'orange
Hi Daniel,

On Tuesday, November 4, 2014 11:54:30 AM UTC+1, Daniel Marjenburgh wrote:

 Hi Jean,

 In this case, we are dealing with 1 key-value pair, so there is only one 
 transient reference all the time. It is not my experience that each update 
 returns a new transient value (here, each update is identical to the 
 original, as per the identical? predicate).


I probably worded myself poorly: When I wrote transient value, I meant the 
contents of a transient, not the reference to it.

I like to think of transients like this: They work exactly like persistent 
data structures, but when any kind of update is performed on the transient, 
the runtime should be allowed to deallocate the old transient head if it 
wants to. If I use transients correctly, I should never see any segfaults 
(or whatever you want to call it) due to transient usage.

Now, the runtime doesn't actually deallocate the transient head, it 
(usually) reuses it for performance. Which means that the old transient 
references are equal to the new transient references, even though the old 
transient contents are overwritten (and therefore invalidated). So even 
though you can use the old transient reference to refer to the new 
transient value, it's not referring to the old transient value.

If it helps you, you can also think of transients as linear types, like the 
ones in Rust. Their constraints are very similar, but correct transient 
usage have to be verified by us, not the compiler. Now, whether that's a 
good idea or not is another matter.
 

 I know you shouldn't use transients in the way I illustrated, but use it 
 as if it always returns a new value. In that scenario, you would not get 
 inconsistent results, as multiple threads would have to coordinate to pass 
 the reference around (as happens in core.async) and the birth-thread check 
 is unnecessary.

 Still, the onus is now put on the user to ensure correct use of transients 
 in a multi-threaded environment, as no warning or error is given anymore. 
 It has always been the case that Clojure makes it hard to write unsafe 
 mutable code, you had to go out of your way. With this change, I feel we 
 are giving up this safeguard a bit too easily.

 Maybe another solution could be to have the birth-thread explicitly 
 relinquish ownership of the transient, for example, by calling 
 (relinquish-transient m). Then the thread that makes the next transient 
 update would become the new owner. If another thread updates a transient 
 while another threads owns it, the usual error is thrown. This way we 
 maintain the safety as before and it becomes a issue for core.async to deal 
 with transients in logical threads, not clojure.core. I guess a go macro 
 could recognize transients in go-blocks and auto-relinguish them before 
 parking operations so that the user can keep thinking in logical threads. 
 I'd like to know how feasible a solution like that would be.


 Op dinsdag 4 november 2014 11:12:08 UTC+1 schreef Jean Niklas L'orange:

 Hi there,

 On Tuesday, November 4, 2014 8:05:03 AM UTC+1, Daniel Marjenburgh wrote:

 I know transients aren't bash-in-place, as they may return new 
 references, but that is not the problem I'm having here.
 If you bash in place, you would get unexpected results, but still the 
 same result every time. The problem here is that the 'value' of the 
 transient is changing underneath you because of another thread.


 To ensure consistency, you must ensure that you update a transient value 
 at most once – all calls (including reads) on the same transient value 
 after an update is illegal/undefined behaviour. Transient updates – minus 
 persistent! – will always return a new transient value, even though the 
 transient returned may be the same reference. So the code

 (let [v (transient {:a 0})
   f1 (future (reduce #(assoc! % (+ (:a %) %2)) v (range 10)))
   f2 (future (reduce #(assoc! % (+ (:a %) %2)) v (range 10)))]
   @f1 @f2 ; wait for futures
   (persistent! @f1))

 will result in undefined behaviour, because the original v is updated 
 twice (and is potentially read after an update). The correct way would be 
 to do the following:

 (let [v {:a 0}
   f1 (future (reduce #(assoc! % (+ (:a %) %2)) (transient v) (range 
 10)))
   f2 (future (reduce #(assoc! % (+ (:a %) %2)) (transient v) (range 
 10)))]
   @f1 @f2 ; wait for futures
   (persistent! @f1))

 I don't see an explicit rule at http://clojure.org/transients stating 
 this, although I feel it is implicit from the bash in-place rule. Perhaps 
 that's something worth adding to the page to avoid confusion.

 --
 Regards,
 Jean Niklas L'orange

  

 Op dinsdag 4 november 2014 06:13:00 UTC+1 schreef Alex Miller:



 On Monday, November 3, 2014 10:44:19 PM UTC-6, Atamert Ölçgen wrote:

 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 

Re: About transients no longer being safe in 1.7-alpha2

2014-11-04 Thread Alex Miller
I think all of these examples violate the usage expectations of transients 
(regardless of release) and you should expect to get confusing results from 
them.

I do not think it's worth modifying core.async go blocks to do anything special 
in this regard (eince go is a macro I don't think you can detect at compile 
time which locals are transients anyways). 

One possibility I've kicked around with some people is deciding at the time you 
create the transient whether it is allowed to cross threads (through a flag or 
something). When you don't need it you could then retain the existing safety 
check.

-- 
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.


Re: About transients no longer being safe in 1.7-alpha2

2014-11-04 Thread Daniel Marjenburgh
Hi Alex,

I understand any concurrent use of transients violates the usage 
expectations. Of course, if you treat any piece of mutable state 
sequentially like transients, you would not run into trouble either.
My concern is purely about the safety that is taken away when transients 
'are' used wrongly. All the examples would've throw exceptions before 
1.7-alpha2, and they don't do so anymore.

Having a single go-block access a transient is valid. Having 2 go-blocks 
access the same transient is not and there is no warning.
If at a certain point you want to 'scale' up from 1 go-block to 2 and don't 
realise it was accessing transients, you are potentially in a lot of 
trouble and there is nothing to warn you.

FWIW, a flag on creating transients to make the dangers explicit would have 
my vote. It would also be in line with being explicit about 
^:volatile-mutable and have the default be safe.

-- 
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.


Re: About transients no longer being safe in 1.7-alpha2

2014-11-04 Thread Atamert Ölçgen
Hi Daniel,


On Wed, Nov 5, 2014 at 3:06 PM, Daniel Marjenburgh dmarjenbu...@gmail.com
wrote:

 My concern is purely about the safety that is taken away when transients
 'are' used wrongly. All the examples would've throw exceptions before
 1.7-alpha2, and they don't do so anymore.


But they would run fine, if you used delay's instead of future's. Same
wrong usage, single threaded. So the issue is not really this new change.

(See my code with delay's earlier)


-- 
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.


About transients no longer being safe in 1.7-alpha2

2014-11-03 Thread Daniel Marjenburgh
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:

(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 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.


Re: About transients no longer being safe in 1.7-alpha2

2014-11-03 Thread Atamert Ölçgen
On Mon, Nov 3, 2014 at 5:57 PM, Daniel Marjenburgh dmarjenbu...@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?




 (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 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.


Re: About transients no longer being safe in 1.7-alpha2

2014-11-03 Thread Alex Miller


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 
 javascript: 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 
 javascript:
 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 javascript:
 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 javascript:.
 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.


Re: About transients no longer being safe in 1.7-alpha2

2014-11-03 Thread Atamert Ölçgen
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 

Re: About transients no longer being safe in 1.7-alpha2

2014-11-03 Thread Alex Miller


On Monday, November 3, 2014 10:44:19 PM UTC-6, Atamert Ölçgen wrote:

 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}.


Right, that is an incorrect usage - it will actually modify with changes 
though, but not in expected ways (this is independent of the change we're 
discussing - you can get the same behavior in a single thread modifying a 
transient without reusing the return).

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.


You can, but not without going pretty far out of normal Clojure code. 
 



 On Tue, Nov 4, 2014 at 11:19 AM, Alex Miller al...@puredanger.com 
 javascript: 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 

Re: About transients no longer being safe in 1.7-alpha2

2014-11-03 Thread Daniel Marjenburgh
Hi Alex.

I know transients aren't bash-in-place, as they may return new references, 
but that is not the problem I'm having here.
If you bash in place, you would get unexpected results, but still the same 
result every time. The problem here is that the 'value' of the transient is 
changing underneath you because of another thread.

Let me change the example a bit:

(let [v (transient {:a 0})
  f1 (future (reduce #(assoc! % (+ (:a %) %2
  f2 (future (reduce #(assoc! % (+ (:a %) %2]
  @f1 @f2 ; wait for futures
  (persistent! f1))

This will also give varying results on each run. If you were to add a 
(println (:a %)) in the reducing fn of f1 you would see the results are not 
the same each time.

Op dinsdag 4 november 2014 06:13:00 UTC+1 schreef Alex Miller:



 On Monday, November 3, 2014 10:44:19 PM UTC-6, Atamert Ölçgen wrote:

 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}.


 Right, that is an incorrect usage - it will actually modify with changes 
 though, but not in expected ways (this is independent of the change we're 
 discussing - you can get the same behavior in a single thread modifying a 
 transient without reusing the return).

 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.


 You can, but not without going pretty far out of normal Clojure code. 
  



 On Tue, Nov 4, 2014 at 11:19 AM, Alex Miller al...@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 

Re: About transients no longer being safe in 1.7-alpha2

2014-11-03 Thread Daniel Marjenburgh
I was a bit too quick there and posted some errors int he code:

(let [v (transient {:a 0})
  f1 (future (reduce #(assoc! % (+ (:a %) %2)) v (range 10)))
  f2 (future (reduce #(assoc! % (+ (:a %) %2)) v (range 10)))]
  @f1 @f2 ; wait for futures
  (persistent! @f1))


  

-- 
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.


Re: About transients no longer being safe in 1.7-alpha2

2014-11-03 Thread Atamert Ölçgen
FWIW I can confirm the following code produces {:a 90} consistently:

(let [v (transient {:a 0})
  f1 (delay (reduce #(assoc! % :a (+ (:a %) %2)) v (range 10)))
  f2 (delay (reduce #(assoc! % :a (+ (:a %) %2)) v (range 10)))]
  @f1 @f2 ; wait for futures
  (persistent! @f1))


Note that there are no future calls here. Clojure 1.5.1

Part of me wants the result to be {:a 45}


On Tue, Nov 4, 2014 at 3:13 PM, Daniel Marjenburgh dmarjenbu...@gmail.com
wrote:

 I was a bit too quick there and posted some errors int he code:

 (let [v (transient {:a 0})
   f1 (future (reduce #(assoc! % (+ (:a %) %2)) v (range 10)))
   f2 (future (reduce #(assoc! % (+ (:a %) %2)) v (range 10)))]
   @f1 @f2 ; wait for futures
   (persistent! @f1))


   --
 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.


Re: About transients no longer being safe in 1.7-alpha2

2014-11-03 Thread Sean Corfield
On Nov 3, 2014, at 11:13 PM, Daniel Marjenburgh dmarjenbu...@gmail.com wrote:
 I was a bit too quick there and posted some errors int he code:

That’s still not quite right. I think you mean:

(let [v (transient {:a 0})
  f1 (future (reduce #(assoc! % :a (+ (:a %) %2)) v (range 10)))
  f2 (future (reduce #(assoc! % :a (+ (:a %) %2)) v (range 10)))]
  @f1 @f2 ; wait for futures
  (persistent! @f1))

Which seems to consistently produce {:a 90} on both Clojure 1.7.0 Alpha 2 and 
Clojure 1.7.0 Alpha 3.

Sean Corfield -- (904) 302-SEAN
An Architect's View -- http://corfield.org/

Perfection is the enemy of the good.
-- Gustave Flaubert, French realist novelist (1821-1880)



-- 
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.