用于在 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]
,无论是通过成功还是失败。