Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 832
trojanfoe Avatar asked Oct 23 '13 20:10

trojanfoe


2 Answers

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
});
like image 80
rob mayoff Avatar answered Sep 28 '22 06:09

rob mayoff


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.

like image 37
Greg Parker Avatar answered Sep 28 '22 05:09

Greg Parker