Reputation: 3184
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
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