Skip to content

Commit aa3e25d

Browse files
committed
Add _RecursiveLock.
1 parent 583b19d commit aa3e25d

File tree

4 files changed

+156
-69
lines changed

4 files changed

+156
-69
lines changed

SwiftTask.xcodeproj/project.pbxproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
48511C5B19C17563002FE03C /* RetainCycleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 48511C5A19C17563002FE03C /* RetainCycleTests.swift */; };
3232
485C31F11A1D619A00040DA3 /* TypeInferenceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 485C31F01A1D619A00040DA3 /* TypeInferenceTests.swift */; };
3333
485C31F21A1D619A00040DA3 /* TypeInferenceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 485C31F01A1D619A00040DA3 /* TypeInferenceTests.swift */; };
34+
487858241B09701F0022E56A /* _RecursiveLock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 487858231B09701F0022E56A /* _RecursiveLock.swift */; };
35+
487858251B09701F0022E56A /* _RecursiveLock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 487858231B09701F0022E56A /* _RecursiveLock.swift */; };
3436
48A1E8221A366F9C007619EB /* SwiftTask.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F46DED4199EDF1000F97868 /* SwiftTask.framework */; };
3537
48A1E8231A366FA8007619EB /* SwiftTask.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 48CD5A0C19AEE3570042B9F1 /* SwiftTask.framework */; };
3638
48B58D7B1A6F255E0068E18C /* _StateMachine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 48B58D7A1A6F255E0068E18C /* _StateMachine.swift */; };
@@ -60,6 +62,7 @@
6062
4822F0D019D00ABF00F5F572 /* SwiftTask-iOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SwiftTask-iOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
6163
48511C5A19C17563002FE03C /* RetainCycleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RetainCycleTests.swift; sourceTree = "<group>"; };
6264
485C31F01A1D619A00040DA3 /* TypeInferenceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TypeInferenceTests.swift; sourceTree = "<group>"; };
65+
487858231B09701F0022E56A /* _RecursiveLock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = _RecursiveLock.swift; sourceTree = "<group>"; };
6366
48B58D7A1A6F255E0068E18C /* _StateMachine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = _StateMachine.swift; sourceTree = "<group>"; };
6467
48CD5A0C19AEE3570042B9F1 /* SwiftTask.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SwiftTask.framework; sourceTree = BUILT_PRODUCTS_DIR; };
6568
/* End PBXFileReference section */
@@ -129,6 +132,7 @@
129132
1F46DEFA199EDF8100F97868 /* SwiftTask.swift */,
130133
1FD7197A1AFE387C00BC38C4 /* Cancellable.swift */,
131134
48B58D7A1A6F255E0068E18C /* _StateMachine.swift */,
135+
487858231B09701F0022E56A /* _RecursiveLock.swift */,
132136
1F46DED7199EDF1000F97868 /* Supporting Files */,
133137
);
134138
path = SwiftTask;
@@ -345,6 +349,7 @@
345349
1F46DEFB199EDF8100F97868 /* SwiftTask.swift in Sources */,
346350
1FD7197B1AFE387C00BC38C4 /* Cancellable.swift in Sources */,
347351
48B58D7B1A6F255E0068E18C /* _StateMachine.swift in Sources */,
352+
487858241B09701F0022E56A /* _RecursiveLock.swift in Sources */,
348353
);
349354
runOnlyForDeploymentPostprocessing = 0;
350355
};
@@ -385,6 +390,7 @@
385390
48CD5A3C19AEEBDF0042B9F1 /* SwiftTask.swift in Sources */,
386391
1FD7197C1AFE387C00BC38C4 /* Cancellable.swift in Sources */,
387392
48B58D7C1A6F255E0068E18C /* _StateMachine.swift in Sources */,
393+
487858251B09701F0022E56A /* _RecursiveLock.swift in Sources */,
388394
);
389395
runOnlyForDeploymentPostprocessing = 0;
390396
};

SwiftTask/SwiftTask.swift

Lines changed: 51 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -637,36 +637,37 @@ extension Task
637637

638638
var completedCount = 0
639639
let totalCount = tasks.count
640+
let lock = _RecursiveLock()
640641

641642
for task in tasks {
642643
task.success { (value: Value) -> Void in
643644

644-
synchronized(self) {
645-
completedCount++
646-
647-
let progressTuple = BulkProgress(completedCount: completedCount, totalCount: totalCount)
648-
progress(progressTuple)
645+
lock.lock()
646+
completedCount++
647+
648+
let progressTuple = BulkProgress(completedCount: completedCount, totalCount: totalCount)
649+
progress(progressTuple)
650+
651+
if completedCount == totalCount {
652+
var values: [Value] = Array()
649653

650-
if completedCount == totalCount {
651-
var values: [Value] = Array()
652-
653-
for task in tasks {
654-
values.append(task.value!)
655-
}
656-
657-
fulfill(values)
654+
for task in tasks {
655+
values.append(task.value!)
658656
}
657+
658+
fulfill(values)
659659
}
660+
lock.unlock()
660661

661662
}.failure { (errorInfo: ErrorInfo) -> Void in
662663

663-
synchronized(self) {
664-
_reject(errorInfo)
665-
666-
for task in tasks {
667-
task.cancel()
668-
}
664+
lock.lock()
665+
_reject(errorInfo)
666+
667+
for task in tasks {
668+
task.cancel()
669669
}
670+
lock.unlock()
670671
}
671672
}
672673

@@ -684,32 +685,33 @@ extension Task
684685
var completedCount = 0
685686
var rejectedCount = 0
686687
let totalCount = tasks.count
688+
let lock = _RecursiveLock()
687689

688690
for task in tasks {
689691
task.success { (value: Value) -> Void in
690692

691-
synchronized(self) {
692-
completedCount++
693+
lock.lock()
694+
completedCount++
695+
696+
if completedCount == 1 {
697+
fulfill(value)
693698

694-
if completedCount == 1 {
695-
fulfill(value)
696-
697-
self.cancelAll(tasks)
698-
}
699+
self.cancelAll(tasks)
699700
}
701+
lock.unlock()
700702

701703
}.failure { (errorInfo: ErrorInfo) -> Void in
702704

703-
synchronized(self) {
704-
rejectedCount++
705+
lock.lock()
706+
rejectedCount++
707+
708+
if rejectedCount == totalCount {
709+
var isAnyCancelled = (tasks.filter { task in task.state == .Cancelled }.count > 0)
705710

706-
if rejectedCount == totalCount {
707-
var isAnyCancelled = (tasks.filter { task in task.state == .Cancelled }.count > 0)
708-
709-
let errorInfo = ErrorInfo(error: nil, isCancelled: isAnyCancelled) // NOTE: Task.any error returns nil (spec)
710-
_reject(errorInfo)
711-
}
711+
let errorInfo = ErrorInfo(error: nil, isCancelled: isAnyCancelled) // NOTE: Task.any error returns nil (spec)
712+
_reject(errorInfo)
712713
}
714+
lock.unlock()
713715
}
714716
}
715717

@@ -728,28 +730,29 @@ extension Task
728730

729731
var completedCount = 0
730732
let totalCount = tasks.count
733+
let lock = _RecursiveLock()
731734

732735
for task in tasks {
733736
task.then { (value: Value?, errorInfo: ErrorInfo?) -> Void in
734737

735-
synchronized(self) {
736-
completedCount++
737-
738-
let progressTuple = BulkProgress(completedCount: completedCount, totalCount: totalCount)
739-
progress(progressTuple)
738+
lock.lock()
739+
completedCount++
740+
741+
let progressTuple = BulkProgress(completedCount: completedCount, totalCount: totalCount)
742+
progress(progressTuple)
743+
744+
if completedCount == totalCount {
745+
var values: [Value] = Array()
740746

741-
if completedCount == totalCount {
742-
var values: [Value] = Array()
743-
744-
for task in tasks {
745-
if task.state == .Fulfilled {
746-
values.append(task.value!)
747-
}
747+
for task in tasks {
748+
if task.state == .Fulfilled {
749+
values.append(task.value!)
748750
}
749-
750-
fulfill(values)
751751
}
752+
753+
fulfill(values)
752754
}
755+
lock.unlock()
753756

754757
}
755758
}
@@ -795,15 +798,4 @@ infix operator ~ { associativity left }
795798
public func ~ <P, V, E>(task: Task<P, V, E>, tryCount: Int) -> Task<P, V, E>
796799
{
797800
return task.try(tryCount)
798-
}
799-
800-
//--------------------------------------------------
801-
// MARK: - Utility
802-
//--------------------------------------------------
803-
804-
internal func synchronized(object: AnyObject, closure: Void -> Void)
805-
{
806-
objc_sync_enter(object)
807-
closure()
808-
objc_sync_exit(object)
809801
}

SwiftTask/_RecursiveLock.swift

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//
2+
// _RecursiveLock.swift
3+
// SwiftTask
4+
//
5+
// Created by Yasuhiro Inami on 2015/05/18.
6+
// Copyright (c) 2015年 Yasuhiro Inami. All rights reserved.
7+
//
8+
9+
import Darwin
10+
11+
internal final class _RecursiveLock
12+
{
13+
private let mutex: UnsafeMutablePointer<pthread_mutex_t>
14+
private let attribute: UnsafeMutablePointer<pthread_mutexattr_t>
15+
16+
internal init()
17+
{
18+
self.mutex = UnsafeMutablePointer.alloc(sizeof(pthread_mutex_t))
19+
self.attribute = UnsafeMutablePointer.alloc(sizeof(pthread_mutexattr_t))
20+
21+
pthread_mutexattr_init(self.attribute)
22+
pthread_mutexattr_settype(self.attribute, PTHREAD_MUTEX_RECURSIVE)
23+
pthread_mutex_init(self.mutex, self.attribute)
24+
}
25+
26+
deinit
27+
{
28+
pthread_mutexattr_destroy(self.attribute)
29+
pthread_mutex_destroy(self.mutex)
30+
}
31+
32+
internal func lock()
33+
{
34+
pthread_mutex_lock(self.mutex)
35+
}
36+
37+
internal func unlock()
38+
{
39+
pthread_mutex_unlock(self.mutex)
40+
}
41+
}

0 commit comments

Comments
 (0)