Skip to content

Commit

Permalink
Added optimizations of OSX
Browse files Browse the repository at this point in the history
  • Loading branch information
trupin committed Jun 10, 2018
1 parent df7fb09 commit c5a0eca
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 14 deletions.
112 changes: 101 additions & 11 deletions Sources/WeaverDI/Builder.swift
Expand Up @@ -43,28 +43,58 @@ final class Builder<I, P>: AnyBuilder {
private extension Builder {

private enum Instance {
case strongLazy(StrongLazyInstance)
case weakLazy(WeakLazyInstance)
case transient(TransientInstance)

case weakLazy(AnyWeakLazyInstance)
case strongLazy(AnyStrongLazyInstance)

init(scope: Scope, body: @escaping Body) {
if scope.isTransient {
self = .transient(TransientInstance(body: body))
} else if scope.isWeak {
self = .weakLazy(WeakLazyInstance(body: body))
if #available(OSX 10.12, *) {
self = .weakLazy(WeakLazyInstance_OSX_10_12(body: body))
} else {
self = .weakLazy(WeakLazyInstance(body: body))
}
} else {
self = .strongLazy(StrongLazyInstance(body: body))
if #available(OSX 10.12, *) {
self = .strongLazy(StrongLazyInstance_OSX_10_12(body: body))
} else {
self = .strongLazy(StrongLazyInstance(body: body))
}
}
}

func getInstance(parameters: () -> P) -> I {
switch self {
case .transient(let instance):
return instance.getInstance(parameters: parameters)
case .strongLazy(let instance):
return instance.getInstance(parameters: parameters)
case .weakLazy(let instance):
return instance.getInstance(parameters: parameters)

case .weakLazy(let _instance):
if #available(OSX 10.12, *) {
guard let instance = _instance as? WeakLazyInstance_OSX_10_12 else {
fatalError("Instance (\(_instance) is not of type \(StrongLazyInstance_OSX_10_12.self).")
}
return instance.getInstance(parameters: parameters)
} else {
guard let instance = _instance as? WeakLazyInstance else {
fatalError("Instance (\(_instance) is not of type \(StrongLazyInstance.self).")
}
return instance.getInstance(parameters: parameters)
}

case .strongLazy(let _instance):
if #available(OSX 10.12, *) {
guard let instance = _instance as? StrongLazyInstance_OSX_10_12 else {
fatalError("Instance (\(_instance) is not of type \(StrongLazyInstance_OSX_10_12.self).")
}
return instance.getInstance(parameters: parameters)
} else {
guard let instance = _instance as? StrongLazyInstance else {
fatalError("Instance (\(_instance) is not of type \(StrongLazyInstance.self).")
}
return instance.getInstance(parameters: parameters)
}
}
}
}
Expand All @@ -90,9 +120,39 @@ private extension Builder {

// MARK: - StrongLazyInstance

private protocol AnyStrongLazyInstance {}

private extension Builder {

final class StrongLazyInstance {
@available(OSX 10.12, *)
final class StrongLazyInstance_OSX_10_12: AnyStrongLazyInstance {

private let body: Body
private var lock = os_unfair_lock()

private var instance: I?

init(body: @escaping Body) {
self.body = body
}

func getInstance(parameters: () -> P) -> I {

os_unfair_lock_lock(&lock)
defer { os_unfair_lock_unlock(&lock) }

if let instance = self.instance {
return instance
}

let instance = body(parameters)
self.instance = instance

return instance
}
}

final class StrongLazyInstance: AnyStrongLazyInstance {

private let body: Body

Expand Down Expand Up @@ -153,9 +213,39 @@ private extension Builder {

// MARK: - WeakLazyInstance

private protocol AnyWeakLazyInstance {}

private extension Builder {

final class WeakLazyInstance {
@available(OSX 10.12, *)
final class WeakLazyInstance_OSX_10_12: AnyWeakLazyInstance {

private let body: Body
private var lock = os_unfair_lock()

private weak var instance: AnyObject?

init(body: @escaping Body) {
self.body = body
}

func getInstance(parameters: () -> P) -> I {

os_unfair_lock_lock(&lock)
defer { os_unfair_lock_unlock(&lock) }

if let instance = self.instance as? I {
return instance
}

let instance = body(parameters)
self.instance = instance as AnyObject

return instance
}
}

final class WeakLazyInstance: AnyWeakLazyInstance {

private let body: Body

Expand Down
6 changes: 3 additions & 3 deletions Tests/WeaverDITests/BuilderTests.swift
Expand Up @@ -66,7 +66,7 @@ final class BuilderTests: XCTestCase {
func xtest_builder_should_ensure_thread_safety_when_building_concurrently() {

var instances = Set<NSObject>()
let lock = NSLock()
let lock = DispatchSemaphore(value: 1)

let dispatchQueue = DispatchQueue(label: "\(DependencyContainerTests.self)", attributes: [.concurrent])

Expand All @@ -78,9 +78,9 @@ final class BuilderTests: XCTestCase {
dispatchQueue.async {
let instance = builder.make()({()})

lock.lock()
lock.wait()
instances.insert(instance)
lock.unlock()
lock.signal()
expectation.fulfill()
}
return expectation
Expand Down

0 comments on commit c5a0eca

Please sign in to comment.