RAC源码分析(一)--RAC基本流程分析

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;
}


  1. 订阅信号,产生了信号的一个订阅者,绑定nextBlock ,在下一步发送信号的时候调用这个nextBlock .
  2. 产生一个核心销毁者(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();
}
[root@rac01 ~]# groupadd -g 1001 dba [root@rac01 ~]# groupadd -g 1002 oinstall [root@rac01 ~]# useradd -u 1001 -g oinstall -G dba oracle [root@rac01 ~]# passwd oracle eth0 inet addr:211.152.14.110 Bcast:211.152.14.255 Mask:255.255.255.0 eth1 inet addr:10.10.10.1 Bcast:10.10.10.255 Mask:255.255.255.0 [root@rac01 ~]# vi /etc/hosts [root@rac01 ~]# cat /etc/hosts # Do not remove the following line, or various programs # that require network functionality will fail. 127.0.0.1 localhost.localdomain localhost 211.152.14.110 rac01 211.152.14.210 vip01 211.152.14.109 rac02 211.152.14.209 vip02 10.10.10.1 priv01 10.10.10.2 priv02 [root@rac01 ~]# su - oracle [oracle@rac01 ~]$ ssh-keygen -t rsa [oracle@rac02 ~]$ ssh-keygen -t rsa [oracle@test .ssh]$ cat id_rsa.pub >> authorized_keys [oracle@test .ssh]$ ssh oracle@rac02 cat /home/oracle/.ssh/id_rsa.pub >> authorized_keys exit 在两个节点上分别执行操作 [oracle@rac01 ~]$ rpm -q binutils compat-db control-center gcc glibc glibc-common gnome-libs libstdc++-3* libstdc++-devel make pdksh sysstat xscreensaver libaio openmotif21 [root@rac01 ~]# vi /etc/sysctl.conf kernel.shmall=2097152 kernel.shmmax=536870912 kernel.shmmni=4096 kernel.sem=250 32000 100 128 fs.file-max=65536 net.ipv4.ip_local_port_range=1024 65000 net.core.rmem_default=262144 net.core.wmem_default=262144 net.core.rmem_max=262144 net.core.wmem_max=262144 [root@rac01 ~]# sysctl -p [root@rac01 ~]# vi /etc/security/limits.conf oracle soft nproc 2047 oracle hard nproc 16384 oracle soft nofile 1024 oracle hard nofile 65536 [root@rac01 ~]# vi /etc/pam.d/login session required /lib/security/pam_limits.so [root@rac01 ~]# vi /etc/profile if [ $USER = "oracle" ];then if [ $SHELL = "/bin/bash" ];then ulimit -p 16384 ulimit -n 65536 else ulimit -u 16384 -n 65536 fi fi [root@test ~]# mkdir /software 将所需软件上传到此处 下载ocfs2内核模块(用uname -r查看版本号) [root@rac01 ~]# uname -r 2.6.9-42.ELsmp http://oss.oracle.com/projects/ocfs2/dist/files/RedHat/RHEL4/i386/1.2.3-1/2.6.9-42.ELsmp/ocfs2 再下载ocfs2 tools(命令和启动脚本)以及ocfs2控制台 http://oss.oracle.com/projects/ocfs2-tools/dist/files/RedHat/RHEL4/i386/1.2.1-1/ocfs2-tools-1.2.1-1.i386.rpm http://oss.oracle.com/projects/ocfs2-tools/dist/files/RedHat/RHEL4/i386/1.2.1-1/ocfs2consol 安装以上三个软件 在rac01上格式化共享磁盘为两个分区,一个用于存储oracle软件,至少3000m,一个用于存储数据库文件及恢复文件,至少4000m vmware-vdiskmanager -c -s 10Gb -a lsilogic -t 3 "F:\rac\share.vmdk" 在vmx文件里面添加如下行,并在vmware setting里面吧磁盘分别加到两个节点上面 scsi0:1.present = "TRUE" scsi0:1.virtualDev = "lsilogic" scsi0:1.sharedBus = "virtual" scsi0:1.mode = "independent-persistent" scsi0:1.filename = "F:\rac\share.vmdk" scsi0:1.deviceType = "disk" disk.locking = "false" diskLib.dataCacheMaxSize = "0" diskLib.dataCacheMaxReadAheadSize = "0" diskLib.DataCacheMinReadAheadSize = "0" diskLib.dataCachePageSize = "9216" diskLib.maxUnsyncedWrites = "0" [root@rac01 ocfs2-1.2.2]# fdisk -l /dev/sdb Disk /dev/sdb: 10.7 GB, 10737418240 bytes 255 heads, 63 sectors/track, 1305 cylinders Units = cylinders of 16065 * 512 = 8225280 bytes Device Boot Start End Blocks Id System /dev/sdb1 1 1305 10482381 5 Extended /dev/sdb5 1 366 2939832 83 Linux /dev/sdb6 367 1305 7542486 83 Linux 重新启动系统rac01和rac02,启动ocfs2console格式化两个分区,并在两个节点上分别挂载共享磁盘,方法自己解决 [root@rac01 ~]# export DISPLAY=211.152.14.200:0.0 [root@rac01 ~]# xhost + [root@rac01 ~]# ocfs2console [root@rac01 ~]# mkdir -p /orac/orahome [root@rac01 ~]# mkdir -p /orac/oradata [root@rac02 ~]# /etc/init.d/o2cb enable mount -t ocfs2 /dev/sdb1 /orac/orahome mount -t ocfs2 -o datavolume,nointr /dev/sdb2 /orac/oradata [root@rac01 ~]# /etc/init.d/o2cb configure [root@rac01 ~]# /etc/init.d/o2cb status [root@rac02 ~]# vi /etc/fstab /dev/sdb1 /orac/orahome ocfs2 _netdev 0 0 /dev/sdb2 /orac/oradata ocfs2 _netdev,datavolume,nointr 0 0 [root@rac01 ~]# mounted.ocfs2 -f Device FS Nodes /dev/sdb1 ocfs2 rac01, rac02 /dev/sdb2 ocfs2 rac01, rac02 两个节点上分别设权限 [root@rac01 ~]# mkdir /orac/crs [root@rac01 crs]# chown -R root:oinstall /orac/crs/ [root@rac01 crs]# chmod -R 775 /orac/crs/ [root@rac01 crs]# chown -R oracle:oinstall /orac/orahome/ [root@rac01 crs]# chmod -R 775 /orac/orahome/ [root@rac01 crs]# chown -R oracle:oinstall /orac/oradata/ [root@rac01 crs]# chmod -R 775 /orac/oradata/ [oracle@rac01 clusterware]$ unzip 10201_clusterware_linux32.zip [oracle@rac01 clusterware]$ ./runInstaller [root@rac01 oradata]# /orac/orahome/oraInventory/orainstRoot.sh [root@rac01 oradata]# /orac/oradata/crs/10.2.0/root.sh
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值