     }
     
     // MARK: Synchronous Inspection
-    
+
     /// Returns `true` the promise hasn't resolved yet.
-    public var isPending: Bool { return _lock.sync { result == nil } }
-    
+    public var isPending: Bool {
+        lock.lock(); defer { lock.unlock() }
+        guard case .pending = state else {
+            return false
+        }
+        return true
+    }
+
     /// Returns the `value` which promise was `fulfilled` with.
-    public var value: T? { return _lock.sync { result?.value } }
-    
+    public var value: T? {
+        lock.lock(); defer { lock.unlock() }
+        guard case let .fulfilled(value) = state else {
+            return nil
+        }
+        return value
+    }
     /// Returns the `error` which promise was `rejected` with.
-    public var error: Error? { return _lock.sync { result?.error } }
-}
-
-extension NSLock {
-    func sync<T>(_ closure: () -> T) -> T {
-        lock(); defer { unlock() };
-        return closure()
-    }
-}
-
-private struct Handlers<T> { // boxed handlers
-    var fulfill = ContiguousArray<(T) -> Void>()
-    var reject = ContiguousArray<(Error) -> Void>()
-}
-
-private enum Result<T> {
-    case fulfilled(T), rejected(Error)
-
-    var value: T? {
-        if case let .fulfilled(val) = self { return val } else { return nil }
-    }
-
-    var error: Error? {
-        if case let .rejected(err) = self { return err } else { return nil }
+    public var error: Error? {
+        lock.lock(); defer { lock.unlock() }
+        guard case let .rejected(error) = state else {
+            return nil
+        }
+        return error
+    }
+
+    // MARK: State (Private)
+
+    private enum State {
+        case pending
+        case fulfilled(T)
+        case rejected(Error)
+    }
+
+    private struct Handlers { // boxed handlers
+        var fulfill = ContiguousArray<(T) -> Void>()
+        var reject = ContiguousArray<(Error) -> Void>()
     }
 }
 
 // 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()
+private let lock = NSLock()

        let _fulfill: (T) -> Void = { value in queue.async { fulfill(value) } }
        let _reject: (Error) -> Void = { error in queue.async { reject(error) } }

        guard let result = _register(fulfill: _fulfill, reject: _reject) else { return }

        // already resolved
        switch result {
        case let .fulfilled(value): _fulfill(value)
        case let .rejected(error): _reject(error)
        }
    }

    /// Registers observer if pending, returns result otherwise.
    private func _register(fulfill: @escaping (T) -> Void, reject: @escaping (Error) -> Void) -> Result<T>? {
        _lock.lock(); defer { _lock.unlock() }
        handlers?.fulfill.append(fulfill)
        handlers?.reject.append(reject)
        return result
    }

    // MARK: Then

    /// 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) {
        handlers = Handlers()
        closure({ self._fulfill($0) }, { self._reject($0) }) // retain self
    }
    
    private func _fulfill(_ value: T) {
        let handlers = _transitionToState(.fulfilled(value))
        handlers?.fulfill.forEach { $0(value) }
    }

    private func _reject(_ error: Error) {
        let handlers = _transitionToState(.rejected(error))
        handlers?.reject.forEach { $0(error) }
    }

    // Return handlers to call if promise was resolved. Returns nil otherwise.
    private func _transitionToState(_ state: State) -> Handlers? {
        lock.lock(); defer { lock.unlock() }
        guard case .pending = self.state else {
            return nil // already resolved
        }
        self.state = state
        let handlers = self.handlers
        self.handlers = nil
        return handlers // returns handlers to be used outside of critical section
    }

    /// 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
    
