Skip to content

Commit 6c86981

Browse files
committed
Merge pull request #3 from ypopovych/master
Fixed pthread runloop
2 parents cd63973 + 8327c56 commit 6c86981

File tree

5 files changed

+208
-183
lines changed

5 files changed

+208
-183
lines changed

ExecutionContext.xcodeproj/project.pbxproj

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@
5252
65FB86CA1C78AC8B0005CD1B /* ImmediateExecutionContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 659E809B1C77457E00DE85B1 /* ImmediateExecutionContext.swift */; };
5353
65FB86CB1C78AC8B0005CD1B /* Result+Some.swift in Sources */ = {isa = PBXBuildFile; fileRef = 659E809D1C77457E00DE85B1 /* Result+Some.swift */; };
5454
65FB86CC1C78ACAE0005CD1B /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 659E80F01C78A70700DE85B1 /* Result.framework */; };
55+
9678EA2D1C7B22DC00E39B17 /* RunLoop.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9678EA2C1C7B22DC00E39B17 /* RunLoop.swift */; };
56+
9678EA2E1C7B22DC00E39B17 /* RunLoop.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9678EA2C1C7B22DC00E39B17 /* RunLoop.swift */; };
57+
9678EA2F1C7B22DC00E39B17 /* RunLoop.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9678EA2C1C7B22DC00E39B17 /* RunLoop.swift */; };
58+
9678EA301C7B22DC00E39B17 /* RunLoop.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9678EA2C1C7B22DC00E39B17 /* RunLoop.swift */; };
5559
/* End PBXBuildFile section */
5660

5761
/* Begin PBXContainerItemProxy section */
@@ -149,6 +153,7 @@
149153
65FB86981C78AA400005CD1B /* ExecutionContext.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ExecutionContext.framework; sourceTree = BUILT_PRODUCTS_DIR; };
150154
65FB86A11C78AA400005CD1B /* ExecutionContextTests-tvOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "ExecutionContextTests-tvOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
151155
65FB86BE1C78AC260005CD1B /* ExecutionContext.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ExecutionContext.framework; sourceTree = BUILT_PRODUCTS_DIR; };
156+
9678EA2C1C7B22DC00E39B17 /* RunLoop.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RunLoop.swift; sourceTree = "<group>"; };
152157
/* End PBXFileReference section */
153158

154159
/* Begin PBXFrameworksBuildPhase section */
@@ -242,6 +247,7 @@
242247
659E80981C77457E00DE85B1 /* DefaultExecutionContext.swift */,
243248
659E80991C77457E00DE85B1 /* DispatchExecutionContext.swift */,
244249
659E809C1C77457E00DE85B1 /* PThreadExecutionContext.swift */,
250+
9678EA2C1C7B22DC00E39B17 /* RunLoop.swift */,
245251
659E809B1C77457E00DE85B1 /* ImmediateExecutionContext.swift */,
246252
65E646DC1C79949C0036D028 /* CustomExecutionContext.swift */,
247253
659E809D1C77457E00DE85B1 /* Result+Some.swift */,
@@ -597,6 +603,7 @@
597603
buildActionMask = 2147483647;
598604
files = (
599605
659E809F1C77457E00DE85B1 /* DispatchExecutionContext.swift in Sources */,
606+
9678EA2D1C7B22DC00E39B17 /* RunLoop.swift in Sources */,
600607
659E80A01C77457E00DE85B1 /* ExecutionContext.swift in Sources */,
601608
65E646DD1C79949C0036D028 /* CustomExecutionContext.swift in Sources */,
602609
659E80A31C77457E00DE85B1 /* Result+Some.swift in Sources */,
@@ -620,6 +627,7 @@
620627
buildActionMask = 2147483647;
621628
files = (
622629
659E80D81C78A4AF00DE85B1 /* DefaultExecutionContext.swift in Sources */,
630+
9678EA2E1C7B22DC00E39B17 /* RunLoop.swift in Sources */,
623631
659E80DA1C78A4B500DE85B1 /* PThreadExecutionContext.swift in Sources */,
624632
65E646DE1C7994A00036D028 /* CustomExecutionContext.swift in Sources */,
625633
659E80DC1C78A4BC00DE85B1 /* Result+Some.swift in Sources */,
@@ -643,6 +651,7 @@
643651
buildActionMask = 2147483647;
644652
files = (
645653
65FB86B01C78AAE00005CD1B /* DefaultExecutionContext.swift in Sources */,
654+
9678EA2F1C7B22DC00E39B17 /* RunLoop.swift in Sources */,
646655
65FB86B21C78AAE50005CD1B /* PThreadExecutionContext.swift in Sources */,
647656
65E646DF1C7994A10036D028 /* CustomExecutionContext.swift in Sources */,
648657
65FB86B41C78AAE50005CD1B /* Result+Some.swift in Sources */,
@@ -666,6 +675,7 @@
666675
buildActionMask = 2147483647;
667676
files = (
668677
65FB86C71C78AC8B0005CD1B /* DefaultExecutionContext.swift in Sources */,
678+
9678EA301C7B22DC00E39B17 /* RunLoop.swift in Sources */,
669679
65FB86C91C78AC8B0005CD1B /* PThreadExecutionContext.swift in Sources */,
670680
65E646E01C7994A20036D028 /* CustomExecutionContext.swift in Sources */,
671681
65FB86CB1C78AC8B0005CD1B /* Result+Some.swift in Sources */,

ExecutionContext/ExecutionContext.swift

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
//===----------------------------------------------------------------------===//
1616

1717
import Foundation
18-
import CoreFoundation
1918
import Result
2019

2120
public typealias Task = () throws -> Void
@@ -171,9 +170,7 @@ public func sleep(timeout:Double) {
171170

172171
@noreturn public func executionContextMain() {
173172
#if os(Linux)
174-
while true {
175-
CFRunLoopRunInMode(defaultMode, 0, true)
176-
}
173+
RunLoop.runForever()
177174
#else
178175
dispatch_main()
179176
#endif

ExecutionContext/PThreadExecutionContext.swift

Lines changed: 11 additions & 176 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,12 @@
1414
//limitations under the License.
1515
//===----------------------------------------------------------------------===//
1616

17-
18-
19-
20-
2117
//////////////////////////////////////////////////////////////////////////
2218
//This file is a temporary solution, just until Dispatch will run on Mac//
2319
//////////////////////////////////////////////////////////////////////////
2420
#if os(Linux)
2521

2622
import Foundation
27-
import CoreFoundation
2823
import Result
2924
#if os(Linux)
3025
import Glibc
@@ -35,10 +30,6 @@
3530
pthread.task?()
3631
return nil
3732
}
38-
39-
private extension NSString {
40-
var cfString: CFString { return unsafeBitCast(self, CFString.self) }
41-
}
4233

4334
private class PThread {
4435
let thread: UnsafeMutablePointer<pthread_t>
@@ -58,136 +49,6 @@
5849
}
5950
}
6051

61-
62-
private class RunLoopFinalizer {
63-
private let rl: CFRunLoop!
64-
init(_ runLoop: CFRunLoop!) {
65-
self.rl = runLoop
66-
}
67-
deinit {
68-
CFRunLoopStop(rl)
69-
}
70-
}
71-
72-
private class RunLoopObject {
73-
private var cfObject:AnyObject? = nil
74-
private let task:SafeTask
75-
private let finalizer:RunLoopFinalizer?
76-
77-
init(_ task:SafeTask, runLoopFinalizer: RunLoopFinalizer?) {
78-
self.task = task
79-
self.finalizer = runLoopFinalizer
80-
}
81-
82-
func addToRunLoop(runLoop:CFRunLoop, mode: CFString) {
83-
if cfObject == nil {
84-
self.cfObject = createCFObject()
85-
}
86-
addCFObject(runLoop, mode: mode)
87-
}
88-
89-
func signal() {}
90-
91-
private func createCFObject() -> AnyObject? { return nil }
92-
93-
private func addCFObject(runLoop:CFRunLoop, mode: CFString) {}
94-
}
95-
96-
private func sourceMain(rls: UnsafeMutablePointer<Void>) {
97-
let runLoopSource = Unmanaged<RunLoopObject>.fromOpaque(COpaquePointer(rls)).takeUnretainedValue()
98-
runLoopSource.cfObject = nil
99-
runLoopSource.task()
100-
}
101-
102-
private func sourceCancel(rls: UnsafeMutablePointer<Void>, rL: CFRunLoop!, mode:CFString!) {
103-
let runLoopSource = Unmanaged<RunLoopObject>.fromOpaque(COpaquePointer(rls)).takeUnretainedValue()
104-
runLoopSource.cfObject = nil
105-
}
106-
107-
private func sourceRetain(rls: UnsafePointer<Void>) -> UnsafePointer<Void> {
108-
Unmanaged<RunLoopObject>.fromOpaque(COpaquePointer(rls)).retain()
109-
return rls
110-
}
111-
112-
private func sourceRelease(rls: UnsafePointer<Void>) {
113-
Unmanaged<RunLoopObject>.fromOpaque(COpaquePointer(rls)).release()
114-
}
115-
116-
private class RunLoopSource : RunLoopObject {
117-
private let priority:Int
118-
119-
init(_ task: SafeTask, priority: Int = 0, finalizer: RunLoopFinalizer?) {
120-
self.priority = priority
121-
super.init(task, runLoopFinalizer: finalizer)
122-
}
123-
124-
deinit {
125-
if let s = cfObject as! CFRunLoopSource? {
126-
if CFRunLoopSourceIsValid(s) { CFRunLoopSourceInvalidate(s) }
127-
}
128-
}
129-
130-
private override func createCFObject() -> AnyObject? {
131-
var context = CFRunLoopSourceContext(
132-
version: 0,
133-
info: UnsafeMutablePointer<Void>(Unmanaged.passUnretained(self).toOpaque()),
134-
retain: sourceRetain,
135-
release: sourceRelease,
136-
copyDescription: nil,
137-
equal: nil,
138-
hash: nil,
139-
schedule: nil,
140-
cancel: sourceCancel,
141-
perform: sourceMain
142-
)
143-
return CFRunLoopSourceCreate(nil, priority, &context)
144-
}
145-
146-
private override func addCFObject(runLoop:CFRunLoop, mode: CFString) {
147-
CFRunLoopAddSource(runLoop, (cfObject as! CFRunLoopSource?)!, mode)
148-
}
149-
150-
override func signal() {
151-
if let s = cfObject as! CFRunLoopSource? {
152-
CFRunLoopSourceSignal(s)
153-
}
154-
}
155-
}
156-
157-
private func timerCallback(timer: CFRunLoopTimer!, rlt: UnsafeMutablePointer<Void>) {
158-
sourceMain(rlt)
159-
}
160-
161-
private class RunLoopDelay : RunLoopObject {
162-
private let delay:CFTimeInterval
163-
164-
init(_ task: SafeTask, delay: CFTimeInterval, finalizer: RunLoopFinalizer?) {
165-
self.delay = delay
166-
super.init(task, runLoopFinalizer: finalizer)
167-
}
168-
169-
deinit {
170-
if let t = cfObject as! CFRunLoopTimer? {
171-
if CFRunLoopTimerIsValid(t) { CFRunLoopTimerInvalidate(t) }
172-
}
173-
}
174-
175-
private override func createCFObject() -> AnyObject? {
176-
var context = CFRunLoopTimerContext(
177-
version: 0,
178-
info: UnsafeMutablePointer<Void>(Unmanaged.passUnretained(self).toOpaque()),
179-
retain: sourceRetain,
180-
release: sourceRelease,
181-
copyDescription: nil
182-
)
183-
return CFRunLoopTimerCreate(nil, CFAbsoluteTimeGetCurrent()+delay, -1, 0, 0, timerCallback, &context)
184-
}
185-
186-
private override func addCFObject(runLoop:CFRunLoop, mode: CFString) {
187-
CFRunLoopAddTimer(runLoop, (cfObject as! CFRunLoopTimer?)!, mode)
188-
}
189-
}
190-
19152
private class ParallelContext : ExecutionContextBase, ExecutionContextType {
19253
func async(task:SafeTask) {
19354
let thread = PThread(task: task)
@@ -207,63 +68,37 @@
20768
}
20869
}
20970

210-
#if !os(Linux)
211-
let defaultMode:CFString = "kCFRunLoopDefaultMode" as NSString
212-
#else
213-
let defaultMode:CFString = "kCFRunLoopDefaultMode".bridge().cfString
214-
#endif
215-
21671
private class SerialContext : ExecutionContextBase, ExecutionContextType {
217-
private let rl:CFRunLoop!
218-
private let finalizer: RunLoopFinalizer?
72+
private let rl:RunLoop
21973

22074
override init() {
221-
var runLoop:CFRunLoop?
75+
var runLoop:RunLoop?
22276
let cond = NSCondition()
22377
cond.lock()
224-
let thread = PThread(task: {
225-
runLoop = CFRunLoopGetCurrent()
78+
PThread(task: {
79+
runLoop = RunLoop.currentRunLoop(true)
22680
cond.signal()
227-
SerialContext.defaultLoop()
228-
})
229-
thread.start()
81+
RunLoop.run()
82+
}).start()
23083
cond.wait()
23184
cond.unlock()
23285
self.rl = runLoop!
233-
finalizer = RunLoopFinalizer(self.rl)
23486
}
23587

236-
init(runLoop:CFRunLoop!) {
88+
init(runLoop:RunLoop) {
23789
rl = runLoop
238-
finalizer = nil
239-
}
240-
241-
#if !os(Linux)
242-
static func defaultLoop() {
243-
while CFRunLoopRunInMode(defaultMode, 0, true) != .Stopped {}
244-
}
245-
#else
246-
static func defaultLoop() {
247-
while CFRunLoopRunInMode(defaultMode, 0, true) != Int32(kCFRunLoopRunStopped) {}
248-
}
249-
#endif
250-
251-
private func performRunLoopObject(rlo: RunLoopObject) {
252-
rlo.addToRunLoop(rl, mode: defaultMode)
253-
rlo.signal()
254-
CFRunLoopWakeUp(rl)
25590
}
25691

25792
func async(task:SafeTask) {
258-
performRunLoopObject(RunLoopSource(task, finalizer: finalizer))
93+
rl.addSource(RunLoopSource(task), mode: RunLoop.defaultMode)
25994
}
26095

26196
func async(after:Double, task:SafeTask) {
262-
performRunLoopObject(RunLoopDelay(task, delay: after, finalizer: finalizer))
97+
rl.addDelay(RunLoopDelay(task, delay: after), mode: RunLoop.defaultMode)
26398
}
26499

265100
func sync<ReturnType>(task:() throws -> ReturnType) throws -> ReturnType {
266-
if rl === CFRunLoopGetCurrent() {
101+
if rl.isCurrent() {
267102
return try task()
268103
} else {
269104
return try syncThroughAsync(task)
@@ -297,7 +132,7 @@
297132
inner.async(after, task: task)
298133
}
299134

300-
public static let main:ExecutionContextType = PThreadExecutionContext(inner: SerialContext(runLoop: CFRunLoopGetMain()))
135+
public static let main:ExecutionContextType = PThreadExecutionContext(inner: SerialContext(runLoop: RunLoop.mainRunLoop()))
301136
public static let global:ExecutionContextType = PThreadExecutionContext(kind: .Parallel)
302137
}
303138

0 commit comments

Comments
 (0)