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.
I would say that class methods like
+ (Locker *)lockerWithLock:(NSLock *)lock;
would probably cause ARC to autorelease the return value (see this article). I think it will be autoreleased unless the method name begins with alloc
, new
, init
, copy
, mutableCopy
(or unless you use special macros to force the compiler into not autoreleasing, NS_RETURNS_RETAINED), the clang ARC documentation is pretty good. An autoreleased object would obviously be a problem given your lock wouldn't be unlocked until the autorelease pool is drained.
I always thought of RAII as being a C/C++ thing where you can allocate objects statically. But I guess you can do it this way, as long as you make well sure that the objects are not autoreleased.