Re: ivar access during -finalize
Re: ivar access during -finalize
- Subject: Re: ivar access during -finalize
- From: Eric Wing <email@hidden>
- Date: Sat, 10 Mar 2012 14:51:59 -0800
Just another angle on your original problem, have you considered using
CFRetain and CFRelease on _myIvar? These are still meaningful in
garbage collection mode. Using CFRetain when you get/create _myIvar,
it would presumably still be alive in your finalize method until you
call CFRelease on it.
-Eric
On 3/9/12, email@hidden <email@hidden> wrote:
>>
>> On 8 Mar 2012, at 16:58, Quincey Morris wrote:
>>
>>>
>>>> A more robust solution is a probably a separate -dispose method.
>>>
>>> Yes, though knowing when to call it can be a puzzle in itself, if there
>>> are multiple references to the object. In general, you'll probably need
>>> to invent a reference counting mechanism to keep track of when it's OK
>>> for your dispose method to actually dispose of things. That sounds ironic
>>> in a GC environment, but there's nothing wrong with reference counting
>>> when you need to keep count. :)
>>
>
> It turns out that chasing my objects around trying to figure out when to
> safely dispose of their object resources is indeed a puzzle.
> I have implemented the following category to provide a reference counting
> mechanism for disposable resources.
> Using a category makes it easy to add this functionality to an existing
> class hierarchy.
>
> Some brief commentary and the code repo is at
> http://github.com/mugginsoft/MGSDisposable
>
> Regards
>
> Jonathan Mitchell
> Mugginsoft LLP
>
> #import <Foundation/Foundation.h>
>
> @interface NSObject (MGSDisposable)
>
> - (void)mgsMakeDisposable;
> - (BOOL)isMgsDisposable;
> - (NSUInteger)mgsDisposalCount;
> - (BOOL)isMgsDisposed;
> - (void)mgsRetainDisposable;
> - (void)mgsReleaseDisposable;
> - (void)mgsDispose;
> - (BOOL)isMgsDisposedWithLogIfTrue;
> - (void)mgsAssociateValue:(id)value withKey:(void *)key;
> - (void)mgsWeaklyAssociateValue:(id)value withKey:(void *)key;
> - (id)mgsAssociatedValueForKey:(void *)key;
> - (void)mgsLogSelector:(SEL)sel;
> @end
>
> #import "NSObject+MGSDisposable.h"
> #import <objc/runtime.h>
>
> // enable logging
> #define MGS_DISPOSAL_LOG
>
> // disable logging
> // comment the line below to enable logging
> #undef MGS_DISPOSAL_LOG
>
> static char mgsDisposableKey;
> NSString * const MGSAllowDisposalKey = @"MGSAllowDisposal";
> NSString * const MGSAllowDisposaValue = @"Yes";
>
> @implementation NSObject (MGSDisposable)
>
> /*
>
> - mgsMakeDisposable
>
> */
> - (void)mgsMakeDisposable
> {
>
> #ifdef MGS_DISPOSAL_LOG
> [self mgsLogSelector:_cmd];
> #endif
>
> // check if already disposable
> if ([self isMgsDisposable]) {
> return;
> }
>
> // assign an initial reference count of 1
> NSNumber *refCount = [NSNumber numberWithUnsignedInteger:1];
> [self mgsAssociateValue:refCount withKey:&mgsDisposableKey];
> }
>
> /*
>
> - isMgsDisposable
>
> */
> - (BOOL)isMgsDisposable
> {
> return ([self mgsDisposalCount] == NSUIntegerMax ? NO : YES);
> }
>
> /*
>
> - mgsDisposalCount
>
> */
> - (NSUInteger)mgsDisposalCount
> {
> NSNumber *refCount = [self mgsAssociatedValueForKey:&mgsDisposableKey];
> if (!refCount) {
> return NSUIntegerMax;
> }
>
> return [refCount unsignedIntegerValue];
> }
>
> /*
>
> - isMgsDisposed
>
> */
> - (BOOL)isMgsDisposed
> {
> NSUInteger refCount = [self mgsDisposalCount];
> return (refCount == 0 ? YES : NO);
> }
>
> /*
>
> - mgsRetainDisposable
>
> */
> - (void)mgsRetainDisposable
> {
>
> #ifdef MGS_DISPOSAL_LOG
> [self mgsLogSelector:_cmd];
> #endif
>
> if (![self isMgsDisposable]) return;
> if ([self isMgsDisposed]) return;
>
> NSUInteger refCount = [self mgsDisposalCount];
> if (refCount == NSUIntegerMax) {
> return;
> }
>
> [self mgsAssociateValue:[NSNumber numberWithUnsignedInteger:++refCount]
> withKey:&mgsDisposableKey];
> }
>
> /*
>
> - mgsReleaseDisposable
>
> */
> - (void)mgsReleaseDisposable
> {
>
> #ifdef MGS_DISPOSAL_LOG
> [self mgsLogSelector:_cmd];
> #endif
>
> if (![self isMgsDisposable]) return;
> if ([self isMgsDisposed]) return;
>
> NSUInteger refCount = [self mgsDisposalCount];
> if (refCount == NSUIntegerMax) {
> return;
> }
>
> // dispose when reference count == 1
> if (refCount == 1) {
> [self mgsAssociateValue:MGSAllowDisposaValue
> withKey:MGSAllowDisposalKey];
> [self mgsDispose];
> } else {
> [self mgsAssociateValue:[NSNumber
> numberWithUnsignedInteger:--refCount] withKey:&mgsDisposableKey];
> }
> }
>
> /*
>
> - mgsDispose
>
> */
> - (void)mgsDispose
> {
>
> #ifdef MGS_DISPOSAL_LOG
> [self mgsLogSelector:_cmd];
> #endif
>
> // we must be disposable
> if (![self isMgsDisposable]) return;
>
> // log and quit if already disposed
> if ([self isMgsDisposedWithLogIfTrue]) return;
>
> // disposal is only valid when the allow disposal key is found
> if (![self mgsAssociatedValueForKey:MGSAllowDisposalKey]) {
> NSLog(@"Disposal is not valid at this time.");
> return;
> }
>
> // mark this object as disposed
> [self mgsAssociateValue:[NSNumber numberWithUnsignedInteger:0]
> withKey:&mgsDisposableKey];
>
> // remove the allow disposal key
> [self mgsAssociateValue:nil withKey:MGSAllowDisposalKey];
> }
>
> /*
>
> - isMgsDisposedWithLogIfTrue
>
> */
> - (BOOL)isMgsDisposedWithLogIfTrue
> {
> if (![self isMgsDisposable]) return NO;
>
> BOOL disposed = [self isMgsDisposed];
> if (disposed) {
> NSLog(@"mgsDispose already called.");
> }
>
> return disposed;
> }
>
> /*
>
> - mgsAssociateValue
>
> */
> - (void)mgsAssociateValue:(id)value withKey:(void *)key
> {
> objc_setAssociatedObject(self, key, value, OBJC_ASSOCIATION_RETAIN);
> }
>
> /*
>
> - mgsWeaklyAssociateValue
>
> */
> - (void)mgsWeaklyAssociateValue:(id)value withKey:(void *)key
> {
> objc_setAssociatedObject(self, key, value, OBJC_ASSOCIATION_ASSIGN);
> }
>
> /*
>
> - mgsAssociatedValueForKey
>
> */
> - (id)mgsAssociatedValueForKey:(void *)key
> {
> return objc_getAssociatedObject(self, key);
> }
>
> /*
>
> - mgsLogSelector:
>
> */
> - (void)mgsLogSelector:(SEL)sel
> {
> NSLog(@"%@ received %@.", self, NSStringFromSelector(sel));
> }
>
> @end
>
>
> _______________________________________________
>
> Cocoa-dev mailing list (email@hidden)
>
> Please do not post admin requests or moderator comments to the list.
> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
>
> Help/Unsubscribe/Update your Subscription:
>
> This email sent to email@hidden
>
--
Beginning iPhone Games Development
http://playcontrol.net/iphonegamebook/
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden