ZhangChn
ZhangChn

Reputation: 3184

Release instance resources once and only once?

I need to protect some code to invalidate a serial queue, in an -invalidate method, so that these codes would be run once, like the dispatch_once in the singleton paradigm.

My intuition is:

@property(nonatomic, readonly, getter=isValid) BOOL valid;
@property(nonatomic) dispatch_queue_t serialQueue;
...
- (void)invalidate {
    if ([self isValid]){
        dispatch_sync(self.serialQueue, ^{
            if ([self isValid]) {
                _valid = NO;
                // relinquish resources here
            }
        });
        if (self.serialQueue) {
            dispatch_release (self.serialQueue);
        }
    }
}

This -invalidate method would be called either explicitly or by -dealloc. And I want to make sure that the resources would be relinquished once and only once.

Is this implementation thread-safe?

Is it a better way to implement a dispatch_once block in a per-instance manner?

@property(nonatomic, readonly) dispatch_once_t invalidated;
...
- (void)invalidate {
    dispatch_once(&_invalidated, ^{
        dispatch_sync(logQueue, ^{
            // double check
            if (self.isValid) {
                self.valid = NO;
                // relinquish things
            }
        }
    }
}

Upvotes: 0

Views: 111

Answers (1)

Martin R
Martin R

Reputation: 539955

If invalidate does not need to be thread-safe, you can just do

- (void)invalidate {
    if ([self isValid]) {
        _valid = NO;
        // relinquish resources here
    }
}

because setting _valid = NO already guarantees that the function is called only once.

Things get a little more complicated if the invalidation must be done in a thread-safe manner. You could use dispatch_once. The disadvantage is that this really works only once. So if you validate your object again later, invalidation will not work anymore.

Alternatively, you can use one of the Synchronization methods, e.g. @synchronized:

- (void)invalidate {
    @synchronized(self) {
        if ([self isValid]) {
            _valid = NO;
            // relinquish resources here
        }
    }
}

Upvotes: 1

Related Questions