     // MARK: Synchronous Inspection
     
     /// Returns `true` the promise hasn't resolved yet.
-    public var isPending: Bool { if case .pending(_) = _state { return true } else { return false } }
+    public var isPending: Bool { return _lock.sync { result == nil } }
     
     /// Returns the `value` which promise was `fulfilled` with.
-    public var value: T? { if case let .fulfilled(val) = _state { return val } else { return nil } }
+    public var value: T? { return _lock.sync { result?.value } }
     
     /// Returns the `error` which promise was `rejected` with.
-    public var error: Error? { if case let .rejected(err) = _state { return err } else { return nil } }
-    
-    private var _state: State<T> {
-        lock.lock(); defer { lock.unlock() }
-        return state
+    public var error: Error? { return _lock.sync { result?.error } }
+}
+
+extension NSLock {
+    func sync<T>(_ closure: () -> T) -> T {
+        lock(); defer { unlock() }
+        return closure()
     }
 }
 

    /// thread. You should start an asynchronous task and call either `fulfill`
    /// or `reject` when it completes.
    public init(_ closure: (_ fulfill: @escaping (T) -> Void, _ reject: @escaping (Error) -> Void) -> Void) {
        closure({ self._fulfill($0) }, { self._reject($0) })
    }
    
    private func _fulfill(_ value: T) {
        _resolve { handlers in
            state = .fulfilled(value)
            // Handlers only contain `queue.async` calls which are fast
            // enough for a critical section (no real need to optimize this).
            handlers.fulfill.forEach { $0(value) }
        }
    }
    
    private func _reject(_ error: Error) {
        _resolve { handlers in
            state = .rejected(error)
            handlers.reject.forEach { $0(error) }
        }
    }
    
    private func _resolve(_ closure: (Handlers<T>) -> Void) {
        lock.lock(); defer { lock.unlock() }
        if case let .pending(handlers) = state { closure(handlers) }
    }
    
    /// Creates a promise fulfilled with a given value.
    public init(value: T) { state = .fulfilled(value) }

    /// Creates a promise rejected with a given error.
    public init(error: Error) { state = .rejected(error) }

    // MARK: Callbacks
    

    var reject = [(Error) -> Void]()
}

private enum Result<T> {
    case fulfilled(T), rejected(Error)
    /// Returns a `value` if the result is success.

    var value: T? {
        if case let .fulfilled(val) = self { return val } else { return nil }
    }

    /// Returns an `error` if the result is failure.
    var error: Error? {
        if case let .rejected(err) = self { return err } else { return nil }
    }
}

// We use the same lock across different tokens because the design of Promise
// prevents potential issues. For example, closures registered with a Promise
// are never executed inside a lock.
private let _lock = NSLock()
