用于在 compare-and-set 原语封装,使用 libkern/OSAtomic.h 软件包中的 Foundation 类型。
AtomicBoolean:对 BOOL 标志的原子封装AtomicInteger:对 NSInteger(32 或 64位,取决于编译_arch_ 架构)的原子封装,具有额外的计数语义(add-and-get,get-and-add)AtomicReference:对 NSObject 的原子封装(见下面的“单个请求”示例)所有原子类都公开一个通用接口
getValue: 和 setValue: 是简单的变量读写操作,保证原子性,而 HOPAtomicReference 除外 —— 因为它处理对象,这需要调整保留计数。操作仍然是原子性的,但对于调用者来说,它们在底层不一定原子性。
compareTo:andSetValue: 如果当前值匹配预期值,则原子性地设置新值。如果成功,返回 YES,否则返回 NO。
getAndSetValue: 原子性地更新底层值,返回旧值。
AtomicInteger 的快速失败节流器@implementation Throttler {
HOPAtomicInteger *_counter;
NSInteger _limit;
}
- (instancetype)initWithLimit:(NSInteger)limit {
self = [super init];
if (self != nil) {
NSParameterAssert(limit > 0);
_counter = [[HOPAtomicInteger alloc] initWithValue:0];
_limit = limit;
}
return self;
}
// Returns YES if executed, NO otherwise
- (BOOL)throttledExec:(void (^)())block {
if ((block == nil) || (_limit <= 0) return YES;
if ([_counter incrementAndGetValue] > _limit) {
[_counter decrementAndGetValue];
return YES;
}
block()
[_counter decrementAndGetValue];
return NO;
}
@end// Throttler *_t
BOOL executed = [_t throttledExec:^{
// Critical section
}];
if (!executed) {
NSLog(@"Resource unavailable");
}@implementation SingleRequestLauncher {
HOPAtomicReference *_ref;
}
- (instancetype)init {
self = [super init];
if (self != nil) {
// Reference never changes, only what it holds.
_ref = [[HOPAtomicReference alloc] init];
}
return self;
}
- (BOOL)launchRequest:(...)... {
id request = // create the request
if ([_ref compareTo:nil andSetObject:request]) {
[request start];
return YES;
}
return NO;
}
- (BOOL)cancelActiveRequest {
id current = [_ref getAndSetObject:nil];
if (current == nil) return NO;
[current cancel];
return YES;
}
@end注意:上面代码假设请求创建在请求完成时会调用
[_ref setObject:nil],无论是通过成功还是失败。