Remove birth-thread check from transients

Description

Transients protect themselves from use by any thread other than the one that creates them. This is good for safety, however it eliminates certain valid usages of transients. For example, usage in a go-block might occur in subsequent invocations across multiple OS threads (but only one logical thread of control).

Current simple test:

user> (def v (transient [])) #'user/v user> (persistent! @(future (conj! v 1))) IllegalAccessError Transient used by non-owner thread clojure.lang.PersistentVector$TransientVector.ensureEditable (PersistentVector.java:464)

Proposal: Remove the owner check from transient collections. (Leave the edit after persistent check as is.) The test above should succeed.

After:

user=> (def v (transient [])) #'user/v user=> (persistent! @(future (conj! v 1))) [1]

The clj-1498-3.diff version of the patch also replaces the AtomicReference<Thread> with AtomicBoolean as we can now track just ownership, not who owns it.

Doc update: Various pieces of documentation will need to be updated with this change, namely http://clojure.org/transients

Patch: clj-1498-3.diff

Alternative: Another idea would be to make this check optional with some kind of option on the transient call (transient coll :check-owner true). Not sure whether what the default would be for that.

Environment

None

Attachments

3
  • 20 Aug 2014, 02:59 PM
  • 13 Aug 2014, 07:42 PM
  • 08 Aug 2014, 05:55 PM

Activity

Show:

Alex Miller August 20, 2014 at 2:59 PM

Enhanced existing generative tests to test random actions against sets, vectors, and both PHM and PAM. Added additional actions to do transient modification actions in other threads as well as originating thread.

Stuart Halloway August 19, 2014 at 5:05 PM

Alex, can you please expand the example test you provided to a generative test that covers the following combinations:

  1. different collection sizes (above and below the ArrayMap size boundary)

  2. different shapes (vector vs. map)

  3. successful use across threads (positive use case this ticket enables)

data_structures.clj has helpers for generating transient interactions that you can build on.

Alex Miller August 13, 2014 at 7:42 PM

New patch that replaces AtomicReference<Thread> with AtomicBoolean.

Jozef Wagner August 9, 2014 at 1:08 PM

I suggest to add a functionality to pass ownership of a transient to the different thread, or to release the ownership by passing nil.

user=> (def v (pass! (transient []) nil)) #'user/v user=> (persistent! @(future (conj! v 1))) [1]

pass! has to be called by current owner thread, or by any thread if the transient is currently released.

Completed

Details

Assignee

Reporter

Approval

Ok

Patch

Code

Priority

Affects versions

Fix versions

Created August 8, 2014 at 5:39 PM
Updated August 29, 2014 at 4:50 PM
Resolved August 29, 2014 at 4:50 PM