 
 */
 public class PromiseSource<Value, Error> {
-  private class PromiseSourceState {
+  internal let dispatchKey: DispatchSpecificKey<Void>
+  internal let dispatchMethod: DispatchMethod
+
+  /// The current state of the PromiseSource
+  private let internalState: PromiseSourceState
+  public var state: State<Value, Error> {
+    return internalState.state
+  }
+
+  /// Print a warning on deinit of an unresolved PromiseSource
+  public var warnUnresolvedDeinit: Bool
+
+  // MARK: Initializers & deinit
+
+  internal convenience init(value: Value) {
+    self.init(state: .resolved(value), dispatchKey: DispatchSpecificKey(), dispatchMethod: .unspecified, warnUnresolvedDeinit: false)
+  }
+
+  internal convenience init(error: Error) {
+    self.init(state: .rejected(error), dispatchKey: DispatchSpecificKey(), dispatchMethod: .unspecified, warnUnresolvedDeinit: false)
+  }
+
+  /// Initialize a new Unresolved PromiseSource
+  ///
+  /// - parameter warnUnresolvedDeinit: Print a warning on deinit of an unresolved PromiseSource
+  public convenience init(dispatch dispatchMethod: DispatchMethod = .unspecified, warnUnresolvedDeinit: Bool = true) {
+    self.init(state: .unresolved, dispatchKey: DispatchSpecificKey(), dispatchMethod: dispatchMethod, warnUnresolvedDeinit: warnUnresolvedDeinit)
+  }
+
+  internal init(state: State<Value, Error>, dispatchKey: DispatchSpecificKey<Void>, dispatchMethod: DispatchMethod, warnUnresolvedDeinit: Bool) {
+    self.internalState = PromiseSourceState(state: state)
+    self.dispatchKey = dispatchKey
+    self.dispatchMethod = dispatchMethod
+    self.warnUnresolvedDeinit = warnUnresolvedDeinit
+
+    if case .queue(let queue) = dispatchMethod {
+      queue.setSpecific(key: dispatchKey, value: ())
+    }
+  }
+
+  deinit {
+    if warnUnresolvedDeinit {
+      switch state {
+      case .unresolved:
+        print("PromiseSource.deinit: WARNING: Unresolved PromiseSource deallocated, maybe retain this object?")
+      default:
+        break
+      }
+    }
+  }
+
+
+  // MARK: Computed properties
+
+  /// Promise related to this PromiseSource
+  public var promise: Promise<Value, Error> {
+    return Promise(source: self)
+  }
+
+
+  // MARK: Resolve / reject
+
+  /// Resolve an Unresolved PromiseSource with supplied value.
+  ///
+  /// When called on a PromiseSource that is already Resolved or Rejected, the call is ignored.
+  public func resolve(_ value: Value) {
+    resolveResult(.value(value))
+  }
+
+
+  /// Reject an Unresolved PromiseSource with supplied error.
+  ///
+  /// When called on a PromiseSource that is already Resolved or Rejected, the call is ignored.
+  public func reject(_ error: Error) {
+    resolveResult(.error(error))
+  }
+
+  internal func resolveResult(_ result: Result<Value, Error>) {
+    let action = internalState.resolve(with: result)
+    callHandlers(action.handlers, with: action.result, dispatchKey: dispatchKey, dispatchMethod: dispatchMethod)
+  }
+
+  // MARK: Adding result handlers
+
+  internal func addOrCallResultHandler(_ handler: @escaping (Result<Value, Error>) -> Void) {
+    if let action = internalState.addHandler(handler) {
+      callHandlers(action.handlers, with: action.result, dispatchKey: dispatchKey, dispatchMethod: dispatchMethod)
+    }
+  }
+}
+
+extension PromiseSource {
+  typealias ResultHandler = (Result<Value, Error>) -> Void
+
+  fileprivate struct PromiseSourceAction {
+    let result: Result<Value, Error>
+    let handlers: [ResultHandler]
+  }
+
+  fileprivate class PromiseSourceState {
     private let lock = NSLock()
     private(set) var state: State<Value, Error>
     private var handlers: [ResultHandler] = []


      case .resolved(let value):
        // Value is already available, call handler immediately
        return (.value(value), [handler])

      case .rejected(let error):
        // Error is already available, call handler immediately
        return (.error(error), [handler])
      }
    }
  }

  typealias ResultHandler = (Result<Value, Error>) -> Void

  internal let dispatchKey: DispatchSpecificKey<Void>
  internal let dispatchMethod: DispatchMethod

  /// The current state of the PromiseSource
  private let internalState: PromiseSourceState
  public var state: State<Value, Error> {
    return internalState.state
  }

  /// Print a warning on deinit of an unresolved PromiseSource
  public var warnUnresolvedDeinit: Bool

  // MARK: Initializers & deinit

  internal convenience init(value: Value) {
    self.init(state: .resolved(value), dispatchKey: DispatchSpecificKey(), dispatchMethod: .unspecified, warnUnresolvedDeinit: false)
  }

  internal convenience init(error: Error) {
    self.init(state: .rejected(error), dispatchKey: DispatchSpecificKey(), dispatchMethod: .unspecified, warnUnresolvedDeinit: false)
  }

  /// Initialize a new Unresolved PromiseSource
  ///
  /// - parameter warnUnresolvedDeinit: Print a warning on deinit of an unresolved PromiseSource
  public convenience init(dispatch dispatchMethod: DispatchMethod = .unspecified, warnUnresolvedDeinit: Bool = true) {
    self.init(state: .unresolved, dispatchKey: DispatchSpecificKey(), dispatchMethod: dispatchMethod, warnUnresolvedDeinit: warnUnresolvedDeinit)
  }

  internal init(state: State<Value, Error>, dispatchKey: DispatchSpecificKey<Void>, dispatchMethod: DispatchMethod, warnUnresolvedDeinit: Bool) {
    self.internalState = PromiseSourceState(state: state)
    self.dispatchKey = dispatchKey
    self.dispatchMethod = dispatchMethod
    self.warnUnresolvedDeinit = warnUnresolvedDeinit

    if case .queue(let queue) = dispatchMethod {
      queue.setSpecific(key: dispatchKey, value: ())
    }
  }

  deinit {
    if warnUnresolvedDeinit {
      switch state {
      case .unresolved:
        print("PromiseSource.deinit: WARNING: Unresolved PromiseSource deallocated, maybe retain this object?")
      default:
        break
      }
    }
  }


  // MARK: Computed properties

  /// Promise related to this PromiseSource
  public var promise: Promise<Value, Error> {
    return Promise(source: self)
  }


  // MARK: Resolve / reject

  /// Resolve an Unresolved PromiseSource with supplied value.
  ///
  /// When called on a PromiseSource that is already Resolved or Rejected, the call is ignored.
  public func resolve(_ value: Value) {
    resolveResult(.value(value))
  }


  /// Reject an Unresolved PromiseSource with supplied error.
  ///
  /// When called on a PromiseSource that is already Resolved or Rejected, the call is ignored.
  public func reject(_ error: Error) {
    resolveResult(.error(error))
  }

  internal func resolveResult(_ result: Result<Value, Error>) {
    let (result, handlersToCall) = internalState.resolve(with: result)
    callHandlers(result, handlers: handlersToCall, dispatchKey: dispatchKey, dispatchMethod: dispatchMethod)
  }

  // MARK: Adding result handlers

  internal func addOrCallResultHandler(_ handler: @escaping (Result<Value, Error>) -> Void) {
    if let (result, handlersToCall) = internalState.addHandler(handler) {
      callHandlers(result, handlers: handlersToCall, dispatchKey: dispatchKey, dispatchMethod: dispatchMethod)
    }
  }
}

internal func callHandlers<T>(_ value: T, handlers: [(T) -> Void], dispatchKey: DispatchSpecificKey<Void>, dispatchMethod: DispatchMethod) {

  for handler in handlers {
    switch dispatchMethod {

      self.state = state
    }

    internal func resolve(with result: Result<Value, Error>) -> PromiseSourceAction {
      lock.lock(); defer { lock.unlock() }

      let handlersToExecute: [ResultHandler]

      switch state {
      case .unresolved:
        state = result.state
