GCDThreadsafe 0.1.3

GCDThreadsafe 0.1.3

测试已测试
Lang语言 Obj-CObjective C
许可 WTFPL
发布最后发布2014年12月

未知的所有者 维护。



  • bryn austin bellomy

// gcd 线程安全

Build Status

这个问题的关键在于使其感觉非常容易实现。这里的规定应该类似于老式的 Objective-C @synchronized 块和 @property (atomic) 声明。

注意:和今天许多人一样,我对强制淘汰 @synchronized/atomic 感兴趣——这是一个非常慢的奶奶级别的代码,在未来的飞船旁边没有任何位置。

您可以使用几乎相同的模式,唯一的真正例外是来自 libextobjc(它仅仅存在以防止与 block 相关的保留周期)的 @strongify(self)@weakify(self) 等样板代码。

关键部分

关键部分是你需要线程安全访问某个资源的代码的一部分。至少对于 GCDThreadsafe 的目的,存在两种类型的关键部分。

  • 关键写入(即,“可变的”部分)
    • 可以写入需要同步/线程安全同步的任何属性/ivars。
    • 作为 async 障碍块分发。快如闪电。已同步但不必立即运行。
  • 关键读取(即,“只读”部分)
    • 作为 sync 障碍块分发。同步并立即运行。(毕竟,您正在从关键部分提取一个值——您在继续之前必须等待,对吧?)
    • 技术上,您可以在这些部分中读取和在写。

可能是一个好主意,在每个部分中只做您声称要做的。在读取部分中读取,在写入部分中写入。不要混淆你的事,老板。有人为那杯饮料付了钱。

自动获取器和自动设置器

是的,GCDThreadsafe 有几个 #define 宏,可以自动实现线程安全类的属性获取器和设置器。这就像能够指定 @property (atomic) 一样,只是它更快且不糟糕。

来自测试的示例

@interface ThreadsafeClass : NSObject <GCDThreadsafe>
    @property (nonatomic, assign, readwrite) NSUInteger counter;
@end


@implementation ThreadsafeClass

@synthesize counter = _counter;

@gcd_threadsafe_implementSetter( NSUInteger, counter, setCounter: )
@gcd_threadsafe_implementGetter_assign( NSUInteger, counter )

// ...

@end

还有一个用于 Objective-C 对象的 @gcd_threadsafe_implementGetter_object() 和用于 GCD 对象的 @gcd_threadsafe_implementGetter_dispatch()(它将自动确定 GCD 对象是否由运行时视为 Objective-C 对象或旧式 C 指针)。

tl;dr(太长了,只读)

要使用所有这些无聊的内容线程化您的类,您只需声明它遵守 GCDThreadsafe 协议即可。

就是这些。

该协议实际上是使用libextobjc的神奇“具体协议”机制定义的,这意味着它自动实现了它声明的所有方法(除非你定义了自己的实现,这通常是不应该做的)。什么都不用做。这很像一个mixin或类扩展,但稍微温和一些(以防你出于某种愚蠢的原因想要覆盖我那些免费无需过问从停车场中开来的默认实现)。

所以在你的Podfile中(你是不是使用CocoaPods,对吧?)

pod 'GCDThreadsafe'

在你的类的头文件中

#import <GCDThreadsafe/GCDThreadsafe.h>

@interface MyClass <GCDThreadsafe>
// ...
@end

并在你的代码中执行关键写操作

@weakify(self);
[self runCriticalMutableSection:^{
    @strongify(self);

    self.someProperty = @"a new value";
    [self someMethodThatMutatesObjectState];
}];

...还有关键读操作

__block NSString *synchronizedValue = nil;

@weakify(self);
[self runCriticalReadSection:^{
    @strongify(self);

    synchronizedValue = [_someHiddenIvar copy];
}];

NSLog( @"synchronizedValue = %@", synchronizedValue );

实际上这就是全部内容。框架将(应该?……可能?)将一切安排得恰到好处。这是一个alpha版本,一定是,所以我非常欢迎任何愿意加入问题队列的反馈。

话又说回来,如果我有足够的勇气把alpha代码放入生产应用中,难道你不应该吗?

自定义队列

如果你是个傻瓜,并且想要用非标准特性(比如,给它一个自定义名称或使其并发)初始化你的队列,你可以在类的-init方法中这样做,在其他事情之前

self = [super init];
if (self)
{
    // the queueCritical property has to be named as such right now... i'll fix this eventually, maybe.
    // also, you should definitely use a SERIAL queue, but if you're feeling ridiculous, you can always
    // give CONCURRENT a shot as well.

    @gcd_threadsafe_init( self.queueCritical, SERIAL, "com.pton.queueCritical" );

    // ...
}

(libextobjc的具体协议真是酷毙了,对吧???)