Skip to content

Commit

Permalink
Recursive lock required in scope resolution
Browse files Browse the repository at this point in the history
  • Loading branch information
hmlongco committed Jul 7, 2022
1 parent e473eed commit bb3cfd6
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 4 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Factory Changelog

### 1.2.4

* Recursive lock required in scope resolution

### 1.2.3

* Streamline critical path through scope caching mechanism
Expand Down
3 changes: 1 addition & 2 deletions Sources/Factory/Factory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@ public struct ParameterFactory<P, T> {

/// Empty convenience class for user dependencies.
public class Container: SharedContainer {

}

/// Base class for all containers.
Expand Down Expand Up @@ -227,7 +226,7 @@ open class SharedContainer {
}
}

private var lock = NSLock()
private var lock = NSRecursiveLock()
private var cache: [UUID:AnyBox] = .init(minimumCapacity: 64)

}
Expand Down
28 changes: 27 additions & 1 deletion Tests/FactoryTests/FactoryDefectTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,34 @@ final class FactoryDefectTests: XCTestCase {
XCTAssertNil(service1.service)
}

// Nested injection when both are on the same scope locks thread. If this test passes then thread wasn't locked...
func testSingletondScopeLocking() throws {
let service1: LockingTestA? = Container.lockingTestA()
XCTAssertNotNil(service1)
let service2: LockingTestA? = Container.lockingTestA()
XCTAssertNotNil(service2)
let text1 = Container.singletonService().text()
let text2 = Container.singletonService().text()
XCTAssertTrue(text1 == text2)
}

}

private class TestLazyInjectionOccursOnce {
fileprivate class TestLazyInjectionOccursOnce {
@LazyInjected(Container.nilSService) var service
}

extension Container {
fileprivate static var lockingTestA = Factory(scope: .singleton) { LockingTestA() }
fileprivate static var lockingTestB = Factory(scope: .singleton) { LockingTestB() }
}

// classes for recursive resolution test
fileprivate class LockingTestA {
@Injected(Container.lockingTestB) var b: LockingTestB
init() {}
}

fileprivate class LockingTestB {
init() {}
}
2 changes: 1 addition & 1 deletion Tests/FactoryTests/FactoryScopeTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ final class FactoryScopeTests: XCTestCase {
override func setUp() {
super.setUp()
Container.Registrations.reset()
Container.Scope.reset()
Container.Scope.reset(includingSingletons: true)
}

func testUniqueScope() throws {
Expand Down

0 comments on commit bb3cfd6

Please sign in to comment.