From 615652b8f84d641b5898193b06d119e198f57190 Mon Sep 17 00:00:00 2001 From: Peter Date: Thu, 9 Feb 2017 20:49:10 +0300 Subject: [PATCH] no message --- SSignalKit/SAtomic.h | 1 + SSignalKit/SAtomic.m | 49 ++++++++++++++++++++++++++++++++-------- SSignalKit/SSubscriber.m | 13 ++++++++--- 3 files changed, 50 insertions(+), 13 deletions(-) diff --git a/SSignalKit/SAtomic.h b/SSignalKit/SAtomic.h index 98aa4da05a..6d3e35b4dc 100644 --- a/SSignalKit/SAtomic.h +++ b/SSignalKit/SAtomic.h @@ -3,6 +3,7 @@ @interface SAtomic : NSObject - (instancetype)initWithValue:(id)value; +- (instancetype)initWithValue:(id)value recursive:(bool)recursive; - (id)swap:(id)newValue; - (id)value; - (id)modify:(id (^)(id))f; diff --git a/SSignalKit/SAtomic.m b/SSignalKit/SAtomic.m index b52e580a82..5f7f3d1032 100644 --- a/SSignalKit/SAtomic.m +++ b/SSignalKit/SAtomic.m @@ -1,10 +1,12 @@ #import "SAtomic.h" -#import +#import @interface SAtomic () { - volatile OSSpinLock _lock; + pthread_mutex_t _lock; + pthread_mutexattr_t _attr; + bool _isRecursive; id _value; } @@ -17,27 +19,54 @@ self = [super init]; if (self != nil) { + pthread_mutex_init(&_lock, NULL); _value = value; } return self; } +- (instancetype)initWithValue:(id)value recursive:(bool)recursive { + self = [super init]; + if (self != nil) + { + _isRecursive = recursive; + + if (recursive) { + pthread_mutexattr_init(&_attr); + pthread_mutexattr_settype(&_attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&_lock, &_attr); + } else { + pthread_mutex_init(&_lock, NULL); + } + + _value = value; + } + return self; +} + +- (void)dealloc { + if (_isRecursive) { + pthread_mutexattr_destroy(&_attr); + } + pthread_mutex_destroy(&_lock); +} + - (id)swap:(id)newValue { id previousValue = nil; - OSSpinLockLock(&_lock); + pthread_mutex_lock(&_lock); previousValue = _value; _value = newValue; - OSSpinLockUnlock(&_lock); + pthread_mutex_unlock(&_lock); return previousValue; } - (id)value { id previousValue = nil; - OSSpinLockLock(&_lock); + pthread_mutex_lock(&_lock); previousValue = _value; - OSSpinLockUnlock(&_lock); + pthread_mutex_unlock(&_lock); return previousValue; } @@ -45,19 +74,19 @@ - (id)modify:(id (^)(id))f { id newValue = nil; - OSSpinLockLock(&_lock); + pthread_mutex_lock(&_lock); newValue = f(_value); _value = newValue; - OSSpinLockUnlock(&_lock); + pthread_mutex_unlock(&_lock); return newValue; } - (id)with:(id (^)(id))f { id result = nil; - OSSpinLockLock(&_lock); + pthread_mutex_lock(&_lock); result = f(_value); - OSSpinLockUnlock(&_lock); + pthread_mutex_unlock(&_lock); return result; } diff --git a/SSignalKit/SSubscriber.m b/SSignalKit/SSubscriber.m index 376bbfdddb..e565b7748d 100644 --- a/SSignalKit/SSubscriber.m +++ b/SSignalKit/SSubscriber.m @@ -50,10 +50,17 @@ - (void)_assignDisposable:(id)disposable { - if (_terminated) - [disposable dispose]; - else + bool dispose = false; + OSSpinLockLock(&_lock); + if (_terminated) { + dispose = true; + } else { _disposable = disposable; + } + OSSpinLockUnlock(&_lock); + if (dispose) { + [disposable dispose]; + } } - (void)_markTerminatedWithoutDisposal