Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit524d1a4

Browse files
author
Alex Belozierov
committed
- refactor and fix performance in PDispatchSerialQueue
1 parent0bcd867 commit524d1a4

File tree

2 files changed

+58
-74
lines changed

2 files changed

+58
-74
lines changed

‎PosixDispatch/DispatchQueue/PDispatchSerialQueue.swift‎

Lines changed: 49 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -8,119 +8,105 @@
88

99
classPDispatchSerialQueue:PDispatchQueueBackend{
1010

11-
fileprivateclassBlocks{
12-
varblocks=[Block]()
11+
privateclassBlocks{
12+
varblocks:ContiguousArray<Block>
1313
init(_ block:@escapingBlock){ blocks=[block]}
1414
}
1515

16-
fileprivateenumItem{
16+
privateenumItem{
1717
case sync(Int),async(Blocks)
1818
}
1919

20-
privateletcondition=PCondition()
21-
privatevarqueue=FifoQueue<Item>(),performing=1
20+
privateletlock=PLock()
21+
privatevarperforming=false
2222

2323
init(){
2424
thread.start()
25-
condition.lockedPerform(block:condition.wait)
25+
lock.lockedPerform(block:threadCondition.wait)
2626
}
2727

28-
// MARK: -Thread
28+
// MARK: -Queue
2929

30-
privatelazyvarthreadCondition=PCondition(lock: condition)
30+
privatevarqueue=FifoQueue<Item>()
3131

32-
private lazyvarthread=PThread{[weak self]in
33-
(self?.condition).map{ $0.lockedPerform(block: $0.signal)}
34-
whilelet self=self{self.performLoop()}
32+
privatefunc startNextItem(){
33+
switch queue.first{
34+
case.sync(let index)?: syncConditions.signal(index: index)
35+
case.async?: threadCondition.signal()
36+
default: performing=false
37+
}
3538
}
3639

37-
// MARK: -RunLoop
40+
// MARK: -Thread
3841

39-
privatefunc performLoop(){
40-
condition.lock()
41-
waitAsync()
42-
letblocks= queue.pop()
43-
condition.unlock()
44-
blocks?.asyncBlocks?.blocks.forEach{$0()}
42+
privatelazyvarthreadCondition=PCondition(lock: lock)
43+
44+
private lazyvarthread=PThread{[weak self]in
45+
self?.lock.lock()
46+
self?.threadCondition.signal()
47+
whilelet self=self{self.runLoop()}
4548
}
4649

47-
privatefunc waitAsync(){
48-
guard performing==2 || queue.first?.asyncBlocks==nilelse{return}
49-
performing-=1
50-
condition.broadcast()
51-
threadCondition.repeatWait(while: performing==1 || queue.first?.asyncBlocks==nil)
52-
performing+=1
50+
privatefunc runLoop(){
51+
threadCondition.wait()
52+
while case.async(let blocks)?= queue.first{
53+
queue.pop()
54+
lock.unlock()
55+
blocks.blocks.forEach{$0()}
56+
lock.lock()
57+
}
58+
startNextItem()
5359
}
5460

5561
// MARK: - Async
5662

57-
@inlinablefuncasync(execute work:@escapingBlock){
58-
condition.lock()
59-
iflet blocks= queue.last?.asyncBlocks{
63+
funcasync(execute work:@escapingBlock){
64+
lock.lock()
65+
defer{ lock.unlock()}
66+
if case.async(let blocks)?= queue.last{
6067
blocks.blocks.append(work)
6168
}else{
6269
queue.push(.async(.init(work)))
63-
if performing==0{ threadCondition.signal()}
70+
if performing{return}
71+
performing=true
72+
threadCondition.signal()
6473
}
65-
condition.unlock()
6674
}
6775

6876
funcasync(flags:DispatchItemFlags, execute work:@escapingBlock){
6977
guard flags.contains(.enforceQoS)else{returnasync(execute: work)}
70-
condition.lock()
78+
lock.lock()
7179
queue.insertInStart(.async(.init(work)))
72-
if performing==0{ threadCondition.signal()}
73-
condition.unlock()
80+
if!performing{ threadCondition.signal()}
81+
lock.unlock()
7482
}
7583

7684
// MARK: - Sync
7785

86+
private lazyvarsyncConditions=PConditionStorage(lock: lock)
7887
privatevarsyncIndex=0
7988

8089
@discardableResultfunc sync<T>(execute work:()throws->T)rethrows->T{
81-
condition.lockedPerform{waitSync(enforce:false)}
82-
defer{condition.lockedPerform(block:finishSync)}
90+
lock.lockedPerform{waitSync(enforce:false)}
91+
defer{lock.lockedPerform(block:startNextItem)}
8392
returntrywork()
8493
}
8594

8695
@discardableResult
8796
func sync<T>(flags:DispatchItemFlags, execute work:()throws->T)rethrows->T{
88-
condition.lockedPerform{waitSync(enforce: flags.contains(.enforceQoS))}
89-
defer{condition.lockedPerform(block:finishSync)}
97+
lock.lockedPerform{waitSync(enforce: flags.contains(.enforceQoS))}
98+
defer{lock.lockedPerform(block:startNextItem)}
9099
returntrywork()
91100
}
92101

93102
privatefunc waitSync(enforce:Bool){
94-
defer{ performing+=1}
95-
if performing==0, queue.isEmpty{return}
103+
defer{ performing=true}
104+
guard performingelse{return}
96105
letindex= syncIndex
97106
syncIndex+=1
98-
enforce? queue.insertInStart(.sync(index)):queue.push(.sync(index))
99-
condition.repeatWait(while: performing!=0 || queue.first?.syncIndex!= index)
107+
queue.push(.sync(index))
108+
syncConditions.wait(index: index)
100109
queue.pop()
101110
}
102111

103-
privatefunc finishSync(){
104-
performing-=1
105-
switch queue.first{
106-
case.sync?: condition.broadcast()
107-
case.async?: threadCondition.signal()
108-
default:break
109-
}
110-
}
111-
112-
}
113-
114-
extensionPDispatchSerialQueue.Item{
115-
116-
varsyncIndex:Int?{
117-
if case.sync(let index)=self{return index}
118-
returnnil
119-
}
120-
121-
varasyncBlocks:PDispatchSerialQueue.Blocks?{
122-
if case.async(let blocks)=self{return blocks}
123-
returnnil
124-
}
125-
126112
}

‎PosixDispatch/Helpers/PConditionStorage.swift‎

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,27 +10,25 @@ class PConditionStorage {
1010

1111
privateletlock:PLock
1212
privatevarconditions=[Int: PCondition]()
13+
privatevarpool=ContiguousArray<PCondition>()
1314

1415
init(lock:PLock){
1516
self.lock= lock
1617
}
1718

18-
@inlinablefunc signal(index:Int, count:Int){
19-
guardlet condition=conditions.removeValue(forKey: index)else{return}
19+
@inlinablefunc signal(index:Int, count:Int=1){
20+
guardlet condition=removeCondition(index: index)else{return}
2021
(0..<count).forEach{ _in condition.signal()}
2122
}
2223

2324
@inlinablefunc broadcast(index:Int){
24-
conditions.removeValue(forKey: index)?.broadcast()
25+
removeCondition(index: index)?.broadcast()
2526
}
2627

27-
@inlinablefunc broadcast(){
28-
conditions.values.forEach{ $0.broadcast()}
29-
conditions.removeAll()
30-
}
31-
32-
@inlinablefunc removeAll(){
33-
conditions.removeAll()
28+
privatefunc removeCondition(index:Int)->PCondition?{
29+
guardlet condition= conditions.removeValue(forKey: index)else{returnnil}
30+
pool.append(condition)
31+
return condition
3432
}
3533

3634
@inlinablefunc wait(index:Int){
@@ -49,7 +47,7 @@ class PConditionStorage {
4947

5048
privatefunc condition(for index:Int)->PCondition{
5149
iflet condition=conditions[index]{return condition}
52-
letcondition=PCondition(lock: lock)
50+
letcondition=pool.popLast()??PCondition(lock: lock)
5351
conditions[index]= condition
5452
return condition
5553
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp