7

在 C++ 下,我有一个Mutex类,我使用这个 RAII 风格的类来确保互斥锁被解锁,不管方法返回的原因是什么:

class MutexLock {
protected:
    Mutex &m_mutex;
public:
    MutexLock(Mutex &mutex) :
        m_mutex(mutex) {
        m_mutex.lock();
    }

    ~MutexLock() {
        m_mutex.unlock();
    }
};

是否有任何理由,并且在使用 ARC 时,等效的 Objective-C 类不能正常工作:

@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

可以通过以下方式使用:

NSLock *_lock;    // instance variable

- (void)myFunc {
    Locker *locker = [[Locker alloc] init];
    locker.lock = _lock;

    return;     // Whenever I like
}

我知道它在 Objective-C 异常的情况下不起作用,与 C++ 版本不同,但假设所有 Objective-C 异常都是致命的,我并不担心。

更新刚刚进行了快速测试,它似乎工作正常。请参阅此要点

4

4 回答 4

7

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
});
于 2014-02-09T21:59:34.503 回答
4

如果你想要 RAII 模式,你应该使用 Objective-C++ 并编写 C++ RAII 类。

ARC 不太可能给您想要的结果。如果某些原因导致它被自动释放,则该对象可能被释放得太晚。如果 ARC 优化器决定不再使用该对象,则该对象可能被过早地释放。

于 2013-10-24T10:13:26.623 回答
3

我会说类方法像

+ (Locker *)lockerWithLock:(NSLock *)lock;

可能会导致 ARC 自动释放返回值(请参阅本文)。我认为它将自动释放,除非方法名称以alloc, new, init,开头copymutableCopy或者除非您使用特殊的宏来强制编译器不自动释放,NS_RETURNS_RETAINED),clang ARC 文档非常好。一个自动释放的对象显然是一个问题,因为在自动释放池耗尽之前你的锁不会被解锁。

我一直认为 RAII 是一个可以静态分配对象的 C/C++ 事物。但我想你可以这样做,只要你确保对象没有自动释放。

于 2013-10-23T21:20:39.007 回答
-1

不要这样做!我最近猎杀了一天左右的错误,直到我发现通过 arc 释放的对象的 tima 和顺序有点随机,在最后一个参考消失后的一段时间。似乎自动释放池是随机弹出的。也没有保留订单。即,仅由另一个对象引用的子对象在其父对象之后被释放。我最终通过自制的“destruct”消息进行手动资源 deininit,并且可能最终将除了一些胶水代码之外的所有代码移植到 c++。我很抱歉人们不得不使用 swift。基本上它是你在 gc 上遇到的所有问题......

于 2019-03-26T15:53:36.400 回答