Closed wrandelshofer closed 2 years ago
Werner, thanks for getting in touch and for proposing the current PR.
You have mentioned that the transients would remain writable after freezing. However, as the interface name Transient
implies, it is meant to be an ephemeral short-lived representation for improving the performance of batched mutations.
The current design in Capsule follows Clojure's concept of transient collections, see summary, including the invariant "Canβt use after returning a persistent version".
Thus, the proposed PR would deviate from the current semantics and design of the transient collections.
Note that rotating the write capability token in freeze()
would as well reset potential performance benefits, since it would be equivalent (in terms of performance) to starting with asTransient()
fresh again.
It appears that you want to use mutable collections by default and create immutable snapshots (by rotating the token and keeping the transient instance alive). Is that correct? Could you elaborate on your use case?
Thank you for your reply. π
My Use Case I have the following use case:
Right now, we have solved this by
This is inefficient due to the frequent cloning, and - in case of 1.b) the application may crash with an UnsupportedOperationException.
I have lots of existing functions (millions of lines). It is easy to refactor setter/getter accesses to business objects, but it is costly to refactor usages of mutable collections everywhere in the code.
I have experimented with interfaces for immutable collections. This solves problems caused by 1.b) but is still inefficient because of the frequent cloning from/to mutable collections.
So, I am now experimenting with persistent collections, that can be efficiently converted from/to mutable collections:
Performance Considerations Yes, I am aware that the proposed freeze() creates a new mutator object, and thus resets potential performance benefits. It is equivalent to calling c=c.freeze().asTransient(). The difference is, that the transient collection does not throw IllegalStateException after a freeze().
This way, I can easily change code in my large code base from businessObject.set(mutableCollection.clone()); to businessObject.set(mutableCollection.freeze()). - The existing code may have references to mutableCollection elsewhere, and may mutate that collection again.
Therefore I had a misconception about the terminology of 'transient' and 'freeze'. I thought 'transient' was the mutable counterpart of 'persistent'.
My proposed code would have turned the transient collections into mutable collections, and thus would be a design change and not just a 'fix' as I had presumed.
Thank you for bringing that to my attention! π I am closing the pull request.π
Hello,
I am integrating the capsule collections into JHotDraw 8. I made a change, which may be of interest to you: I have simplified/enhanced the use of the writeCapabilityToken/mutator in capsule
I have added a new class "UniqueIdentity". This class is now used as the new writeCapabilityToken/mutator for transient collections instead of an AtomicReference. I could have used class "Object", because all I need is a unique identity, but it easier to track with a distinct class.
The freeze() methods of a transient collection now creates a new UniqueIdentity instead of setting the AtomicReference of its writeCapabailityToken/mutator to null. This allows to get rid of the IllegalStateExceptions in the transient collection classes. A transient collection class can now stay mutable after it has created a freezed version of itself.
With best regards, Werner