Cleaner cleanup
Peter Levart
peter.levart at gmail.com
Mon May 16 10:57:07 UTC 2016
Correction in line...
On 05/16/2016 12:54 PM, Peter Levart wrote:
> Hi Christoph,
>
>
> On 05/16/2016 10:37 AM, Christoph Engelbert wrote:
>> Hey Peter,
>>
>> First of all, I really love this Cleanup API!
>> Anyhow I think it would make sense to have Cleanable extend
>> AutoCloseable for exactly the use case you rendered in your JavaDoc
>> of the Cleaner class.
>>
>> Made up example:
>> public <T> T execute(BufferAction bufferAction) {
>> Buffer buffer = allocateBuffer();
>> try (Cleanable wrapper = cleaner.register(buffer,
>> Buffer::deallocate) {
>> bufferAction.execute(buffer);
>> }
>> }
>>
>> I agree that you probably want to encapsulate the cleaner
>> registration and cleaning action but for frameworks it might be
>> beneficial to have a common utility method implementing a pattern
>> such as the one above.
>>
>> Chris
>
> I think the Cleaner API is more suitable to be used inside various
> classes that themselves implement AutoCloseable rather than as an
> (optional) aspect on top of them. So your example would simply read:
>
> public <T> T execute(BufferAction bufferAction) {
> try (Buffer buffer = allocateBuffer()) {
> bufferAction.execute(buffer);
> }
> }
>
> There's no point in doing both things as in your example: using
> try-with-resources + the Cleaner API on top. try-with-resources
> already guarantees cleanup.
Sorry, the following:
> *Cleanable* API is meant to be used inside otherwise *AutoCleanable*
> implementations to shield the user from native resource leaks if the
> user forgets to use or can't use try-with-resources.
Should read:
*Cleaner* API is meant to be used inside otherwise *AutoCloseable*
implementations to shield the user from native resource leaks if the
user forgets to use or can't use try-with-resources.
>
> Regards, Peter
>
>>
>>> On 16 May 2016, at 00:08, Peter Levart <peter.levart at gmail.com> wrote:
>>>
>>> Hi Roger and others,
>>>
>>> When the new Cleaner API was created the implementation of
>>> Cleanable(s) was split into the low-level abstract
>>> [Soft|Weak|Phantom]Cleanable classes to be used internally for
>>> purposes where the footprint matters and their corresponding
>>> CleanerImpl.[Soft|Weak|Phantom]CleanableRef subclasses used as
>>> implementations that take a Runnable cleanup action and are exposed
>>> via the public Cleaner API.
>>>
>>> When thinking of possible JDK internal use cases for the low-level
>>> API, I came to the conclusion that [Soft|Weak|Phantom]Cleanable
>>> classes are not suitable as is, because in cases where footprint
>>> matters, it is usually also the case that the number of
>>> [Soft|Weak|Phantom]Cleanable instances created is larger and that
>>> construction performance also matters. Especially multi-threaded
>>> construction. I'm thinking of the use cases of auto-cleanable
>>> concurrent data structures. In such use cases, the present features
>>> of [Soft|Weak|Phantom]Cleanable classes, namely the guaranteed
>>> just-once cleanup action invocation and keeping the Cleanable
>>> instance reachable until the cleanup action is performed, are
>>> actually not needed and just present footprint and performance
>>> (contention) overhead. They also present an overhead as they don't
>>> allow GC to automatically collect the Cleanable instances if the
>>> data structure containing them becomes unreachable and corresponding
>>> registered cleanup actions obsolete.
>>>
>>> The mentioned features are important for public Cleaner.Cleanable
>>> instances as they are usually used for cleanup of native resources
>>> where the performance of their creation is not so drastically
>>> important and where there is no intrinsic data structure to hold
>>> them reachable.
>>>
>>> I propose to move those features from the
>>> [Soft|Weak|Phantom]Cleanable classes down the hierarchy to the
>>> CleanerImpl.[Soft|Weak|Phantom]CleanableRef subclasses:
>>>
>>> http://cr.openjdk.java.net/~plevart/jdk9-dev/Cleaner.cleanup/webrev.01/
>>>
>>>
>>> In this change I also removed the
>>> CleanerImpl.[Soft|Weak]CleanableRef subclasses as they are not
>>> needed and I believe will never be. I also renamed the
>>> CleanerImpl.PhantomCleanableRef subclass to
>>> CleanerImpl.PhantomCleanableImpl.
>>>
>>> Changes to the implementation are straightforward. The most work was
>>> put into the corresponding test. I did some clean-up to it and also
>>> changed it to accommodate for the new behavior of
>>> [Soft|Weak|Phantom]Cleanable classes. The changes speak for itself.
>>> One of the not-so obvious changes was to replace the
>>> CleanableCase.clearRef() action with the
>>> CleanableCase.releaseReferent() action. The old clearRef() action
>>> did not serve any purpose. Whether this method was called or not,
>>> the behavior of the corresponding Cleanable was unchanged as the
>>> Reference instance (referenced from the 'ref' field) was always of
>>> the same strength as the Cleanable itself. So clearing it could not
>>> affect the behavior of the Cleanable.
>>>
>>> I changed 'ref' to hold a direct reference to the referent and
>>> renamed the field to 'referent'. I changed the EV_XXX int constants
>>> to Event enum constants with helper methods used in
>>> CleanableCase.expectedCleanups() method that now returns the number
>>> of expected cleanup invocations - in the PhantomCleanableImpl case
>>> this is the number of expected cleanup action invocations while in
>>> the plain XxxCleanable subclass cases it is the number of
>>> Cleanable.clean() method invocations. I added the no-actions case to
>>> both PhantomCleanableImpl and XxxCleanable cases and extended the
>>> number and combinations of XxxCleanable cases.
>>>
>>> The checkCleaned() method was extended to verify that the number of
>>> cleanup invocations is *no more* and no less then the expected.
>>>
>>> See how WeakKey test is now simplified. This is the typical use-case
>>> for WeakCleanable I was talking about.
>>>
>>>
>>> So, what do you think of this cleanup?
>>>
>>>
>>> Regards, Peter
>>>
>
>
More information about the core-libs-dev
mailing list