c++objective-cmutexraii

Will this RAII-style Objective-C class work?


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.


Solution

  • 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.