Under C++, I have a Mutex
class, and I use this RAII-style class to ensure the mutex is unlocked, regardless of the reason for the method return:
class MutexLock {
protected:
Mutex &m_mutex;
public:
MutexLock(Mutex &mutex) :
m_mutex(mutex) {
m_mutex.lock();
}
~MutexLock() {
m_mutex.unlock();
}
};
Is there any reason, and when using ARC, that an equivalent Objective-C class wouldn't work just as well:
@interface Locker : NSObject {
NSLock *_lock;
}
- (void)setLock:(NSLock *)lock;
@end
@implementation Locker
- (void)setLock:(NSLock *)lock {
[_lock unlock];
_lock = lock;
[_lock lock];
}
- (void)dealloc {
self.lock = nil;
}
@end
Which might be used in the following way:
NSLock *_lock; // instance variable
- (void)myFunc {
Locker *locker = [[Locker alloc] init];
locker.lock = _lock;
return; // Whenever I like
}
I understand it won't work in the case of Objective-C exceptions, unlike the C++ version, but assuming all Objective-C exceptions are fatal, I'm not worried about that.
UPDATE Just knocked-up a quick test, and it appears to be working fine. See this gist.
Better API: use a block:
void performBlockWithLock(NSLock *lock, void (^block)(void)) {
[lock lock];
block();
[lock unlock];
}
Example:
NSLock *someLock = ...;
performBlockWithLock(someLock, ^{
// your code here
});
If you want RAII patterns, you should use Objective-C++ and write C++ RAII classes.
ARC is unlikely to give you the result you want. The object may be deallocated too late, if something causes it to be autoreleased. The object may be deallocated too early, if the ARC optimizer decides the object is no longer used.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With