123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990 |
- //
- // RACDisposable.m
- // ReactiveObjC
- //
- // Created by Josh Abernathy on 3/16/12.
- // Copyright (c) 2012 GitHub, Inc. All rights reserved.
- //
- #import "RACDisposable.h"
- #import "RACScopedDisposable.h"
- #import <libkern/OSAtomic.h>
- @interface RACDisposable () {
- // A copied block of type void (^)(void) containing the logic for disposal,
- // a pointer to `self` if no logic should be performed upon disposal, or
- // NULL if the receiver is already disposed.
- //
- // This should only be used atomically.
- void * volatile _disposeBlock;
- }
- @end
- @implementation RACDisposable
- #pragma mark Properties
- - (BOOL)isDisposed {
- return _disposeBlock == NULL;
- }
- #pragma mark Lifecycle
- - (instancetype)init {
- self = [super init];
- _disposeBlock = (__bridge void *)self;
- OSMemoryBarrier();
- return self;
- }
- - (instancetype)initWithBlock:(void (^)(void))block {
- NSCParameterAssert(block != nil);
- self = [super init];
- _disposeBlock = (void *)CFBridgingRetain([block copy]);
- OSMemoryBarrier();
- return self;
- }
- + (instancetype)disposableWithBlock:(void (^)(void))block {
- return [(RACDisposable *)[self alloc] initWithBlock:block];
- }
- - (void)dealloc {
- if (_disposeBlock == NULL || _disposeBlock == (__bridge void *)self) return;
- CFRelease(_disposeBlock);
- _disposeBlock = NULL;
- }
- #pragma mark Disposal
- - (void)dispose {
- void (^disposeBlock)(void) = NULL;
- while (YES) {
- void *blockPtr = _disposeBlock;
- if (OSAtomicCompareAndSwapPtrBarrier(blockPtr, NULL, &_disposeBlock)) {
- if (blockPtr != (__bridge void *)self) {
- disposeBlock = CFBridgingRelease(blockPtr);
- }
- break;
- }
- }
- if (disposeBlock != nil) disposeBlock();
- }
- #pragma mark Scoped Disposables
- - (RACScopedDisposable *)asScopedDisposable {
- return [RACScopedDisposable scopedDisposableWithDisposable:self];
- }
- @end
|