Skip to content

Commit

Permalink
Replace NSRecursiveLock with pthread mutex in PropertyBox.
Browse files Browse the repository at this point in the history
  • Loading branch information
andersio committed May 13, 2017
1 parent a51695c commit af6a7f6
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 6 deletions.
27 changes: 25 additions & 2 deletions Sources/Atomic.swift
Original file line number Diff line number Diff line change
Expand Up @@ -143,11 +143,34 @@ internal class Lock {
internal final class PthreadLock: Lock {
private let _lock: UnsafeMutablePointer<pthread_mutex_t>

override init() {
init(recursive: Bool = false) {
_lock = .allocate(capacity: 1)
_lock.initialize(to: pthread_mutex_t())

let status = pthread_mutex_init(_lock, nil)
let attr = UnsafeMutablePointer<pthread_mutexattr_t>.allocate(capacity: 1)
attr.initialize(to: pthread_mutexattr_t())
pthread_mutexattr_init(attr)

defer {
pthread_mutexattr_destroy(attr)
attr.deinitialize()
attr.deallocate(capacity: 1)
}

#if DEBUG
pthread_mutexattr_settype(attr, Int32(recursive ? PTHREAD_MUTEX_RECURSIVE : PTHREAD_MUTEX_ERRORCHECK))
#else
pthread_mutexattr_settype(attr, Int32(recursive ? PTHREAD_MUTEX_RECURSIVE : PTHREAD_MUTEX_NORMAL))
#endif

#if os(iOS) || os(macOS) || os(tvOS) || os(watchOS)
// The pthread mutex implementation of Darwin guarantees fairness by
// default. Since fairness is not a concern of our reactive primitives
// anyway, it can be disabled.
pthread_mutexattr_setpolicy_np(attr, _PTHREAD_MUTEX_POLICY_FIRSTFIT)
#endif

let status = pthread_mutex_init(_lock, attr)
assert(status == 0, "Unexpected pthread mutex error code: \(status)")

super.init()
Expand Down
14 changes: 10 additions & 4 deletions Sources/Property.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import Foundation
#if os(iOS) || os(macOS) || os(tvOS) || os(watchOS)
import Darwin.POSIX.pthread
#else
import Glibc
#endif
import enum Result.NoError

/// Represents a property that allows observation of its changes.
Expand Down Expand Up @@ -701,16 +705,18 @@ public final class MutableProperty<Value>: ComposableMutablePropertyProtocol {
/// The requirement of a `Value?` storage from composed properties prevents further
/// implementation sharing with `MutableProperty`.
private final class PropertyBox<Value> {
private let lock = NSRecursiveLock()
private let lock: Lock.PthreadLock
private var _value: Value
var value: Value { return modify { $0 } }

init(_ value: Value) {
self._value = value
_value = value
lock = Lock.PthreadLock(recursive: true)
}

func modify<Result>(didSet: (Value) -> Void = { _ in }, _ action: (inout Value) throws -> Result) rethrows -> Result {
lock.lock(); defer { didSet(_value); lock.unlock() }
lock.lock()
defer { didSet(_value); lock.unlock() }
return try action(&_value)
}
}
Expand Down

0 comments on commit af6a7f6

Please sign in to comment.