RAC源码分析(一)--RAC基本流程分析
程序员文章站
2024-03-23 22:32:40
...
RAC流程分析
1. 信号产生
实际开发中,一个信号的产生 可以是UI RACobserver Sequence …
下面来看看createSignal都做了什么事情
//1.
+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
//把block封装进来 利用多态原理返回 RACDynamicSignal
return [RACDynamicSignal createSignal:didSubscribe];//传入的参数就是一个block
}
//2
+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
RACDynamicSignal *signal = [[self alloc] init];
// 绑定block,在订阅信号的时候调用
signal->_didSubscribe = [didSubscribe copy];
return [signal setNameWithFormat:@"+createSignal:"];
}
创建了一个信号,并且把didSubscribeBlock保存起来,在信号被订阅的时候,执行这didSubscribeBlock
2. 订阅信号
// 1
- (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock {
NSCParameterAssert(nextBlock != NULL);
//产生一个订阅者 绑定nextBlock
RACSubscriber *o = [RACSubscriber subscriberWithNext:nextBlock error:NULL completed:NULL];
//这是self 是RACDynamicSignal 是本方法的调用者
return [self subscribe:o];
}
// 2
- (RACDisposable *)subscribe:(id<RACSubscriber>)subscriber {
NSCParameterAssert(subscriber != nil);
// 产生 RACCompoundDisposable : 核心销毁者
RACCompoundDisposable *disposable = [RACCompoundDisposable compoundDisposable];
// RACPassthroughSubscriber 核心订阅者
/*
subscriber : 订阅者
signal : RACDynamicSignal 信号
disposable : 销毁者
传入者三个参数后 分别用三个属性保存住
三个属性保存住 是为了后续使用
*/
subscriber = [[RACPassthroughSubscriber alloc] initWithSubscriber:subscriber signal:self disposable:disposable];
if (self.didSubscribe != NULL) {
// RACScheduler(封装了一个GCD)
RACDisposable *schedulingDisposable = [RACScheduler.subscriptionScheduler schedule:^{
//把核心订阅者传出去了, 这里的subscriber 就是create信号时block中的参数,订阅者
//执行创建信号时保存的didSubscribeBlock
RACDisposable *innerDisposable = self.didSubscribe(subscriber);
//添加我的要销毁者的对象 把要销毁的对象都装进去 根据情况统一销毁
[disposable addDisposable:innerDisposable];
}];
[disposable addDisposable:schedulingDisposable];
}
return disposable;
}
- 订阅信号,产生了信号的一个订阅者,绑定nextBlock ,在下一步发送信号的时候调用这个nextBlock .
- 产生一个核心销毁者(RACCompoundDisposable),产生一个核心订阅者(RACPassthroughSubscriber),核心订阅者保存了销毁者,1中创建的订阅者,以及信号.执行didSubscribe(subscriber)
3.发送信号
- (void)sendNext:(id)value {
if (self.disposable.disposed) return;
if (RACSIGNAL_NEXT_ENABLED()) {
RACSIGNAL_NEXT(cleanedSignalDescription(self.signal), cleanedDTraceString(self.innerSubscriber.description), cleanedDTraceString([value description]));
}
//真正的订阅
[self.innerSubscriber sendNext:value];
}
- (void)sendNext:(id)value {
//加锁
@synchronized (self) {
void (^nextBlock)(id) = [self.next copy];
if (nextBlock == nil) return;
nextBlock(value);
}
互斥锁,然后执行创建订阅者时保存的nextBlock
4. 销毁
在订阅信号的时候,产生了一个核心订阅者(RACPassthroughSubscriber)和一个核心销毁者(RACCompoundDisposable),
而核心订阅者内部持有了订阅者(subscriber),信号(signal),以及核心销毁者(disposable),
核心销毁者(disposable)可以被添加其他的销毁者,存入内部的一个数组中,在自身被释放的时候,会把数组中的也全部释放.
比如订阅者被self持有
[subscriber sendNext:@"123"];
self.subscriber = subscriber;
要想释放掉信号相关的内存,就必须self.subscriber = nil.
当订阅者被释放,在dealloc方法中
- (void)dealloc {
//核心销毁者开始执行dispose方法
[self.disposable dispose];
}
核心销毁者的dispose
- (void)dispose {
#if RACCompoundDisposableInlineCount
//C 数组 type * a[2]
RACDisposable *inlineCopy[RACCompoundDisposableInlineCount];
#endif
CFArrayRef remainingDisposables = NULL;
pthread_mutex_lock(&_mutex);
{
_disposed = YES;
#if RACCompoundDisposableInlineCount
for (unsigned i = 0; i < RACCompoundDisposableInlineCount; i++) {
inlineCopy[i] = _inlineDisposables[i];
//当前的销毁数组,一个个的清理 数组移除
_inlineDisposables[i] = nil;
}
#endif
remainingDisposables = _disposables;
_disposables = NULL;
}
pthread_mutex_unlock(&_mutex);
#if RACCompoundDisposableInlineCount
// Dispose outside of the lock in case the compound disposable is used
// recursively.
for (unsigned i = 0; i < RACCompoundDisposableInlineCount; i++) {
[inlineCopy[i] dispose];//存入的disposable各自调用各自的dispose方法
}
#endif
if (remainingDisposables == NULL) return;
CFIndex count = CFArrayGetCount(remainingDisposables);
CFArrayApplyFunction(remainingDisposables, CFRangeMake(0, count), &disposeEach, NULL);
CFRelease(remainingDisposables);
}
存进核心销毁者的各个disposable调用dispose方法
[RACDisposable dispose]
- (void)dispose {
void (^disposeBlock)(void) = NULL;
//遍历去找销毁对象
while (YES) {
void *blockPtr = _disposeBlock;
// OSAtomicCompareAndSwapPtrBarrier(v1,v2,v3)
/*
v1 与 v3 匹配 相同就返回yes
然后把v2 赋值给v3 也就是 = null
*/
if (OSAtomicCompareAndSwapPtrBarrier(blockPtr, NULL, &_disposeBlock)) {
if (blockPtr != (__bridge void *)self) {
disposeBlock = CFBridgingRelease(blockPtr);
}
break;
}
}
// 持有的block,成为了临时变量,执行完,block也就释放了
if (disposeBlock != nil) disposeBlock();
}
上一篇: 5.Go语言基本类型 —— 浮点型
下一篇: 汇编实验——外设控制
推荐阅读
-
RAC源码分析(一)--RAC基本流程分析
-
[Abp 源码分析] 一、Abp 框架启动流程分析
-
[Abp 源码分析] 一、Abp 框架启动流程分析
-
Springboot 的一些基础源码分析 (一)SpringApplication执行流程
-
Tomcat初始化源码流程分析(图解及源码注释) (一)
-
MapReduce运行流程源码分析(一)
-
Hadoop源码学习笔记之NameNode启动流程分析一:源码环境搭建和项目模块及NameNode结构简单介绍
-
Spring AOP源码分析(三)Spring AOP中的一些基本接口及其概念
-
记一次因网卡心跳故障引发RAC节点重启故障分析
-
Glide源码分析(一),基本加载代码流程