From 464b0e42aa0bef9dd8717a52d3651830ba08144d Mon Sep 17 00:00:00 2001 From: Yehor Popovych Date: Mon, 22 Feb 2016 12:58:43 +0200 Subject: [PATCH 1/3] New version of pthread context --- ExecutionContext/ExecutionContext.swift | 5 +- .../PThreadExecutionContext.swift | 187 ++---------------- ExecutionContext/RunLoop.swift | 171 ++++++++++++++++ 3 files changed, 183 insertions(+), 180 deletions(-) create mode 100644 ExecutionContext/RunLoop.swift diff --git a/ExecutionContext/ExecutionContext.swift b/ExecutionContext/ExecutionContext.swift index c44948e..257565b 100644 --- a/ExecutionContext/ExecutionContext.swift +++ b/ExecutionContext/ExecutionContext.swift @@ -15,7 +15,6 @@ //===----------------------------------------------------------------------===// import Foundation -import CoreFoundation import Result public typealias Task = () throws -> Void @@ -171,9 +170,7 @@ public func sleep(timeout:Double) { @noreturn public func executionContextMain() { #if os(Linux) - while true { - CFRunLoopRunInMode(defaultMode, 0, true) - } + RunLoop.runForever() #else dispatch_main() #endif diff --git a/ExecutionContext/PThreadExecutionContext.swift b/ExecutionContext/PThreadExecutionContext.swift index d66ada3..82c678e 100644 --- a/ExecutionContext/PThreadExecutionContext.swift +++ b/ExecutionContext/PThreadExecutionContext.swift @@ -14,17 +14,12 @@ //limitations under the License. //===----------------------------------------------------------------------===// - - - - ////////////////////////////////////////////////////////////////////////// //This file is a temporary solution, just until Dispatch will run on Mac// ////////////////////////////////////////////////////////////////////////// #if os(Linux) import Foundation - import CoreFoundation import Result #if os(Linux) import Glibc @@ -35,10 +30,6 @@ pthread.task?() return nil } - - private extension NSString { - var cfString: CFString { return unsafeBitCast(self, CFString.self) } - } private class PThread { let thread: UnsafeMutablePointer @@ -58,136 +49,6 @@ } } - - private class RunLoopFinalizer { - private let rl: CFRunLoop! - init(_ runLoop: CFRunLoop!) { - self.rl = runLoop - } - deinit { - CFRunLoopStop(rl) - } - } - - private class RunLoopObject { - private var cfObject:AnyObject? = nil - private let task:SafeTask - private let finalizer:RunLoopFinalizer? - - init(_ task:SafeTask, runLoopFinalizer: RunLoopFinalizer?) { - self.task = task - self.finalizer = runLoopFinalizer - } - - func addToRunLoop(runLoop:CFRunLoop, mode: CFString) { - if cfObject == nil { - self.cfObject = createCFObject() - } - addCFObject(runLoop, mode: mode) - } - - func signal() {} - - private func createCFObject() -> AnyObject? { return nil } - - private func addCFObject(runLoop:CFRunLoop, mode: CFString) {} - } - - private func sourceMain(rls: UnsafeMutablePointer) { - let runLoopSource = Unmanaged.fromOpaque(COpaquePointer(rls)).takeUnretainedValue() - runLoopSource.cfObject = nil - runLoopSource.task() - } - - private func sourceCancel(rls: UnsafeMutablePointer, rL: CFRunLoop!, mode:CFString!) { - let runLoopSource = Unmanaged.fromOpaque(COpaquePointer(rls)).takeUnretainedValue() - runLoopSource.cfObject = nil - } - - private func sourceRetain(rls: UnsafePointer) -> UnsafePointer { - Unmanaged.fromOpaque(COpaquePointer(rls)).retain() - return rls - } - - private func sourceRelease(rls: UnsafePointer) { - Unmanaged.fromOpaque(COpaquePointer(rls)).release() - } - - private class RunLoopSource : RunLoopObject { - private let priority:Int - - init(_ task: SafeTask, priority: Int = 0, finalizer: RunLoopFinalizer?) { - self.priority = priority - super.init(task, runLoopFinalizer: finalizer) - } - - deinit { - if let s = cfObject as! CFRunLoopSource? { - if CFRunLoopSourceIsValid(s) { CFRunLoopSourceInvalidate(s) } - } - } - - private override func createCFObject() -> AnyObject? { - var context = CFRunLoopSourceContext( - version: 0, - info: UnsafeMutablePointer(Unmanaged.passUnretained(self).toOpaque()), - retain: sourceRetain, - release: sourceRelease, - copyDescription: nil, - equal: nil, - hash: nil, - schedule: nil, - cancel: sourceCancel, - perform: sourceMain - ) - return CFRunLoopSourceCreate(nil, priority, &context) - } - - private override func addCFObject(runLoop:CFRunLoop, mode: CFString) { - CFRunLoopAddSource(runLoop, (cfObject as! CFRunLoopSource?)!, mode) - } - - override func signal() { - if let s = cfObject as! CFRunLoopSource? { - CFRunLoopSourceSignal(s) - } - } - } - - private func timerCallback(timer: CFRunLoopTimer!, rlt: UnsafeMutablePointer) { - sourceMain(rlt) - } - - private class RunLoopDelay : RunLoopObject { - private let delay:CFTimeInterval - - init(_ task: SafeTask, delay: CFTimeInterval, finalizer: RunLoopFinalizer?) { - self.delay = delay - super.init(task, runLoopFinalizer: finalizer) - } - - deinit { - if let t = cfObject as! CFRunLoopTimer? { - if CFRunLoopTimerIsValid(t) { CFRunLoopTimerInvalidate(t) } - } - } - - private override func createCFObject() -> AnyObject? { - var context = CFRunLoopTimerContext( - version: 0, - info: UnsafeMutablePointer(Unmanaged.passUnretained(self).toOpaque()), - retain: sourceRetain, - release: sourceRelease, - copyDescription: nil - ) - return CFRunLoopTimerCreate(nil, CFAbsoluteTimeGetCurrent()+delay, -1, 0, 0, timerCallback, &context) - } - - private override func addCFObject(runLoop:CFRunLoop, mode: CFString) { - CFRunLoopAddTimer(runLoop, (cfObject as! CFRunLoopTimer?)!, mode) - } - } - private class ParallelContext : ExecutionContextBase, ExecutionContextType { func async(task:SafeTask) { let thread = PThread(task: task) @@ -207,63 +68,37 @@ } } -#if !os(Linux) - let defaultMode:CFString = "kCFRunLoopDefaultMode" as NSString -#else - let defaultMode:CFString = "kCFRunLoopDefaultMode".bridge().cfString -#endif - private class SerialContext : ExecutionContextBase, ExecutionContextType { - private let rl:CFRunLoop! - private let finalizer: RunLoopFinalizer? + private let rl:RunLoop override init() { - var runLoop:CFRunLoop? + var runLoop:RunLoop? let cond = NSCondition() cond.lock() - let thread = PThread(task: { - runLoop = CFRunLoopGetCurrent() + PThread(task: { + runLoop = RunLoop.currentRunLoop(true) cond.signal() - SerialContext.defaultLoop() - }) - thread.start() + RunLoop.run() + }).start() cond.wait() cond.unlock() self.rl = runLoop! - finalizer = RunLoopFinalizer(self.rl) } - init(runLoop:CFRunLoop!) { + init(runLoop:RunLoop) { rl = runLoop - finalizer = nil - } - - #if !os(Linux) - static func defaultLoop() { - while CFRunLoopRunInMode(defaultMode, 0, true) != .Stopped {} - } - #else - static func defaultLoop() { - while CFRunLoopRunInMode(defaultMode, 0, true) != Int32(kCFRunLoopRunStopped) {} - } - #endif - - private func performRunLoopObject(rlo: RunLoopObject) { - rlo.addToRunLoop(rl, mode: defaultMode) - rlo.signal() - CFRunLoopWakeUp(rl) } func async(task:SafeTask) { - performRunLoopObject(RunLoopSource(task, finalizer: finalizer)) + rl.addSource(RunLoopSource(task), mode: RunLoop.defaultMode) } func async(after:Double, task:SafeTask) { - performRunLoopObject(RunLoopDelay(task, delay: after, finalizer: finalizer)) + rl.addDelay(RunLoopDelay(task, delay: after), mode: RunLoop.defaultMode) } func sync(task:() throws -> ReturnType) throws -> ReturnType { - if rl === CFRunLoopGetCurrent() { + if rl.isCurrent() { return try task() } else { return try syncThroughAsync(task) @@ -297,7 +132,7 @@ inner.async(after, task: task) } - public static let main:ExecutionContextType = PThreadExecutionContext(inner: SerialContext(runLoop: CFRunLoopGetMain())) + public static let main:ExecutionContextType = PThreadExecutionContext(inner: SerialContext(runLoop: RunLoop.mainRunLoop())) public static let global:ExecutionContextType = PThreadExecutionContext(kind: .Parallel) } diff --git a/ExecutionContext/RunLoop.swift b/ExecutionContext/RunLoop.swift new file mode 100644 index 0000000..1584f1a --- /dev/null +++ b/ExecutionContext/RunLoop.swift @@ -0,0 +1,171 @@ +//===--- RunLoop.swift ------------------------------------------------------===// +//Copyright (c) 2016 Daniel Leping (dileping) +// +//Licensed under the Apache License, Version 2.0 (the "License"); +//you may not use this file except in compliance with the License. +//You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, software +//distributed under the License is distributed on an "AS IS" BASIS, +//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +//See the License for the specific language governing permissions and +//limitations under the License. +//===----------------------------------------------------------------------===// + +import Foundation +import CoreFoundation + +#if os(Linux) + + private extension NSString { + var cfString: CFString { return unsafeBitCast(self, CFString.self) } + } + + private class RunLoopCallbackInfo { + private var task: SafeTask + private var runLoops: [RunLoop] = [] + + init(_ task: SafeTask) { + self.task = task + } + + func run() { + task() + } + } + + private func runLoopCallbackInfoRun(i: UnsafeMutablePointer) { + let info = Unmanaged.fromOpaque(COpaquePointer(i)).takeUnretainedValue() + info.run() + } + + private func runLoopCallbackInfoRetain(i: UnsafePointer) -> UnsafePointer { + Unmanaged.fromOpaque(COpaquePointer(i)).retain() + return i + } + + private func runLoopCallbackInfoRelease(i: UnsafePointer) { + Unmanaged.fromOpaque(COpaquePointer(i)).release() + } + + private protocol RunLoopCallback { + var info : RunLoopCallbackInfo { get } + var cfObject: AnyObject { get } + } + + struct RunLoopSource : RunLoopCallback { + private let info : RunLoopCallbackInfo + private let priority : Int + + private var cfObject : AnyObject { + var context = CFRunLoopSourceContext( + version: 0, + info: UnsafeMutablePointer(Unmanaged.passUnretained(info).toOpaque()), + retain: runLoopCallbackInfoRetain, + release: runLoopCallbackInfoRelease, + copyDescription: nil, + equal: nil, + hash: nil, + schedule: nil, + cancel: nil, + perform: runLoopCallbackInfoRun + ) + return CFRunLoopSourceCreate(nil, priority, &context) + } + + init(_ task: SafeTask, priority: Int = 0) { + self.info = RunLoopCallbackInfo(task) + self.priority = priority + } + } + + private func timerRunCallback(timer: CFRunLoopTimer!, i: UnsafeMutablePointer) { + runLoopCallbackInfoRun(i) + } + + struct RunLoopDelay : RunLoopCallback { + private let info : RunLoopCallbackInfo + private let delay: Double + + private var cfObject : AnyObject { + var context = CFRunLoopTimerContext( + version: 0, + info: UnsafeMutablePointer(Unmanaged.passUnretained(info).toOpaque()), + retain: runLoopCallbackInfoRetain, + release: runLoopCallbackInfoRelease, + copyDescription: nil + ) + return CFRunLoopTimerCreate(nil, CFAbsoluteTimeGetCurrent()+delay, -1, 0, 0, timerRunCallback, &context) + } + + init(_ task: SafeTask, delay: Double) { + self.delay = delay + self.info = RunLoopCallbackInfo(task) + } + } + + class RunLoop { + private let cfRunLoop: CFRunLoop! + private let autoStop: Bool + + #if !os(Linux) + static let defaultMode:NSString = "kCFRunLoopDefaultMode" as NSString + #else + static let defaultMode:NSString = "kCFRunLoopDefaultMode".bridge() + #endif + + init(_ runLoop: CFRunLoop, autoStop: Bool = true) { + self.cfRunLoop = runLoop + self.autoStop = autoStop + } + + deinit { + if autoStop && cfRunLoop != nil { + CFRunLoopStop(cfRunLoop) + } + } + + static func currentRunLoop(autoStop: Bool = false) -> RunLoop { + return RunLoop(CFRunLoopGetCurrent(), autoStop: autoStop) + } + + static func mainRunLoop() -> RunLoop { + return RunLoop(CFRunLoopGetMain(), autoStop: false) + } + + func isCurrent() -> Bool { + return cfRunLoop === CFRunLoopGetCurrent() + } + + static func run() { + runInMode(RunLoop.defaultMode) + } + + static func runInMode(mode: NSString) { + #if !os(Linux) + while CFRunLoopRunInMode(mode.cfString, Double.infinity, false) != .Stopped {} + #else + while CFRunLoopRunInMode(mode.cfString, Double.infinity, false) != Int32(kCFRunLoopRunStopped) {} + #endif + } + + @noreturn static func runForever() { + while true { run() } + } + + func addSource(rls: RunLoopSource, mode: NSString) { + rls.info.runLoops.append(self) + CFRunLoopAddSource(cfRunLoop, unsafeBitCast(rls.cfObject, CFRunLoopSource.self), mode.cfString) + CFRunLoopSourceSignal(unsafeBitCast(rls.cfObject, CFRunLoopSource.self)) + CFRunLoopWakeUp(cfRunLoop) + } + + func addDelay(rld: RunLoopDelay, mode: NSString) { + rld.info.runLoops.append(self) + CFRunLoopAddTimer(cfRunLoop, unsafeBitCast(rld.cfObject, CFRunLoopTimer.self), mode.cfString) + CFRunLoopWakeUp(cfRunLoop) + } + } +#endif \ No newline at end of file From b856edfd7912b556b34ccc7f1a0160ce7d1b3fe5 Mon Sep 17 00:00:00 2001 From: Yehor Popovych Date: Mon, 22 Feb 2016 13:22:30 +0200 Subject: [PATCH 2/3] Fixed runloop bug --- ExecutionContext.xcodeproj/project.pbxproj | 10 ++++ ExecutionContext/RunLoop.swift | 60 +++++++++++-------- .../ExecutionContextTests.swift | 6 +- 3 files changed, 49 insertions(+), 27 deletions(-) diff --git a/ExecutionContext.xcodeproj/project.pbxproj b/ExecutionContext.xcodeproj/project.pbxproj index 3677082..8f65c7f 100644 --- a/ExecutionContext.xcodeproj/project.pbxproj +++ b/ExecutionContext.xcodeproj/project.pbxproj @@ -52,6 +52,10 @@ 65FB86CA1C78AC8B0005CD1B /* ImmediateExecutionContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 659E809B1C77457E00DE85B1 /* ImmediateExecutionContext.swift */; }; 65FB86CB1C78AC8B0005CD1B /* Result+Some.swift in Sources */ = {isa = PBXBuildFile; fileRef = 659E809D1C77457E00DE85B1 /* Result+Some.swift */; }; 65FB86CC1C78ACAE0005CD1B /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 659E80F01C78A70700DE85B1 /* Result.framework */; }; + 9678EA2D1C7B22DC00E39B17 /* RunLoop.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9678EA2C1C7B22DC00E39B17 /* RunLoop.swift */; }; + 9678EA2E1C7B22DC00E39B17 /* RunLoop.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9678EA2C1C7B22DC00E39B17 /* RunLoop.swift */; }; + 9678EA2F1C7B22DC00E39B17 /* RunLoop.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9678EA2C1C7B22DC00E39B17 /* RunLoop.swift */; }; + 9678EA301C7B22DC00E39B17 /* RunLoop.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9678EA2C1C7B22DC00E39B17 /* RunLoop.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -149,6 +153,7 @@ 65FB86981C78AA400005CD1B /* ExecutionContext.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ExecutionContext.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 65FB86A11C78AA400005CD1B /* ExecutionContextTests-tvOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "ExecutionContextTests-tvOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 65FB86BE1C78AC260005CD1B /* ExecutionContext.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ExecutionContext.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 9678EA2C1C7B22DC00E39B17 /* RunLoop.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RunLoop.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -242,6 +247,7 @@ 659E80981C77457E00DE85B1 /* DefaultExecutionContext.swift */, 659E80991C77457E00DE85B1 /* DispatchExecutionContext.swift */, 659E809C1C77457E00DE85B1 /* PThreadExecutionContext.swift */, + 9678EA2C1C7B22DC00E39B17 /* RunLoop.swift */, 659E809B1C77457E00DE85B1 /* ImmediateExecutionContext.swift */, 65E646DC1C79949C0036D028 /* CustomExecutionContext.swift */, 659E809D1C77457E00DE85B1 /* Result+Some.swift */, @@ -597,6 +603,7 @@ buildActionMask = 2147483647; files = ( 659E809F1C77457E00DE85B1 /* DispatchExecutionContext.swift in Sources */, + 9678EA2D1C7B22DC00E39B17 /* RunLoop.swift in Sources */, 659E80A01C77457E00DE85B1 /* ExecutionContext.swift in Sources */, 65E646DD1C79949C0036D028 /* CustomExecutionContext.swift in Sources */, 659E80A31C77457E00DE85B1 /* Result+Some.swift in Sources */, @@ -620,6 +627,7 @@ buildActionMask = 2147483647; files = ( 659E80D81C78A4AF00DE85B1 /* DefaultExecutionContext.swift in Sources */, + 9678EA2E1C7B22DC00E39B17 /* RunLoop.swift in Sources */, 659E80DA1C78A4B500DE85B1 /* PThreadExecutionContext.swift in Sources */, 65E646DE1C7994A00036D028 /* CustomExecutionContext.swift in Sources */, 659E80DC1C78A4BC00DE85B1 /* Result+Some.swift in Sources */, @@ -643,6 +651,7 @@ buildActionMask = 2147483647; files = ( 65FB86B01C78AAE00005CD1B /* DefaultExecutionContext.swift in Sources */, + 9678EA2F1C7B22DC00E39B17 /* RunLoop.swift in Sources */, 65FB86B21C78AAE50005CD1B /* PThreadExecutionContext.swift in Sources */, 65E646DF1C7994A10036D028 /* CustomExecutionContext.swift in Sources */, 65FB86B41C78AAE50005CD1B /* Result+Some.swift in Sources */, @@ -666,6 +675,7 @@ buildActionMask = 2147483647; files = ( 65FB86C71C78AC8B0005CD1B /* DefaultExecutionContext.swift in Sources */, + 9678EA301C7B22DC00E39B17 /* RunLoop.swift in Sources */, 65FB86C91C78AC8B0005CD1B /* PThreadExecutionContext.swift in Sources */, 65E646E01C7994A20036D028 /* CustomExecutionContext.swift in Sources */, 65FB86CB1C78AC8B0005CD1B /* Result+Some.swift in Sources */, diff --git a/ExecutionContext/RunLoop.swift b/ExecutionContext/RunLoop.swift index 1584f1a..1648002 100644 --- a/ExecutionContext/RunLoop.swift +++ b/ExecutionContext/RunLoop.swift @@ -52,27 +52,33 @@ import CoreFoundation private protocol RunLoopCallback { var info : RunLoopCallbackInfo { get } - var cfObject: AnyObject { get } + var cfObject: AnyObject { mutating get } } struct RunLoopSource : RunLoopCallback { private let info : RunLoopCallbackInfo private let priority : Int + private var _source: CFRunLoopSource! = nil private var cfObject : AnyObject { - var context = CFRunLoopSourceContext( - version: 0, - info: UnsafeMutablePointer(Unmanaged.passUnretained(info).toOpaque()), - retain: runLoopCallbackInfoRetain, - release: runLoopCallbackInfoRelease, - copyDescription: nil, - equal: nil, - hash: nil, - schedule: nil, - cancel: nil, - perform: runLoopCallbackInfoRun - ) - return CFRunLoopSourceCreate(nil, priority, &context) + mutating get { + if _source == nil { + var context = CFRunLoopSourceContext( + version: 0, + info: UnsafeMutablePointer(Unmanaged.passUnretained(info).toOpaque()), + retain: runLoopCallbackInfoRetain, + release: runLoopCallbackInfoRelease, + copyDescription: nil, + equal: nil, + hash: nil, + schedule: nil, + cancel: nil, + perform: runLoopCallbackInfoRun + ) + _source = CFRunLoopSourceCreate(nil, priority, &context) + } + return _source + } } init(_ task: SafeTask, priority: Int = 0) { @@ -88,16 +94,22 @@ import CoreFoundation struct RunLoopDelay : RunLoopCallback { private let info : RunLoopCallbackInfo private let delay: Double + private var _timer: CFRunLoopTimer! = nil private var cfObject : AnyObject { - var context = CFRunLoopTimerContext( - version: 0, - info: UnsafeMutablePointer(Unmanaged.passUnretained(info).toOpaque()), - retain: runLoopCallbackInfoRetain, - release: runLoopCallbackInfoRelease, - copyDescription: nil - ) - return CFRunLoopTimerCreate(nil, CFAbsoluteTimeGetCurrent()+delay, -1, 0, 0, timerRunCallback, &context) + mutating get { + if _timer == nil { + var context = CFRunLoopTimerContext( + version: 0, + info: UnsafeMutablePointer(Unmanaged.passUnretained(info).toOpaque()), + retain: runLoopCallbackInfoRetain, + release: runLoopCallbackInfoRelease, + copyDescription: nil + ) + _timer = CFRunLoopTimerCreate(nil, CFAbsoluteTimeGetCurrent()+delay, -1, 0, 0, timerRunCallback, &context) + } + return _timer + } } init(_ task: SafeTask, delay: Double) { @@ -155,14 +167,14 @@ import CoreFoundation while true { run() } } - func addSource(rls: RunLoopSource, mode: NSString) { + func addSource(var rls: RunLoopSource, mode: NSString) { rls.info.runLoops.append(self) CFRunLoopAddSource(cfRunLoop, unsafeBitCast(rls.cfObject, CFRunLoopSource.self), mode.cfString) CFRunLoopSourceSignal(unsafeBitCast(rls.cfObject, CFRunLoopSource.self)) CFRunLoopWakeUp(cfRunLoop) } - func addDelay(rld: RunLoopDelay, mode: NSString) { + func addDelay(var rld: RunLoopDelay, mode: NSString) { rld.info.runLoops.append(self) CFRunLoopAddTimer(cfRunLoop, unsafeBitCast(rld.cfObject, CFRunLoopTimer.self), mode.cfString) CFRunLoopWakeUp(cfRunLoop) diff --git a/Tests/ExecutionContext/ExecutionContextTests.swift b/Tests/ExecutionContext/ExecutionContextTests.swift index 0187ef0..b39ae65 100644 --- a/Tests/ExecutionContext/ExecutionContextTests.swift +++ b/Tests/ExecutionContext/ExecutionContextTests.swift @@ -159,9 +159,9 @@ extension ExecutionContextTests : XCTestCaseProvider { ("testParallel", testParallel), ("testGlobal", testGlobal), ("testMain", testMain), - ("testMain", testCustomOnGlobal), - ("testMain", testCustomOnMain), - ("testMain", testCustomSimple) + ("testCustomOnGlobal", testCustomOnGlobal), + ("testCustomOnMain", testCustomOnMain), + ("testCustomSimple", testCustomSimple) ] } } From 8327c5686ea34acea458c863c33f0b6612373deb Mon Sep 17 00:00:00 2001 From: Yehor Popovych Date: Mon, 22 Feb 2016 14:23:24 +0200 Subject: [PATCH 3/3] Fixed version for linux --- ExecutionContext/RunLoop.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ExecutionContext/RunLoop.swift b/ExecutionContext/RunLoop.swift index 1648002..872103a 100644 --- a/ExecutionContext/RunLoop.swift +++ b/ExecutionContext/RunLoop.swift @@ -55,13 +55,13 @@ import CoreFoundation var cfObject: AnyObject { mutating get } } - struct RunLoopSource : RunLoopCallback { + class RunLoopSource : RunLoopCallback { private let info : RunLoopCallbackInfo private let priority : Int private var _source: CFRunLoopSource! = nil private var cfObject : AnyObject { - mutating get { + get { if _source == nil { var context = CFRunLoopSourceContext( version: 0, @@ -91,13 +91,13 @@ import CoreFoundation runLoopCallbackInfoRun(i) } - struct RunLoopDelay : RunLoopCallback { + class RunLoopDelay : RunLoopCallback { private let info : RunLoopCallbackInfo private let delay: Double private var _timer: CFRunLoopTimer! = nil private var cfObject : AnyObject { - mutating get { + get { if _timer == nil { var context = CFRunLoopTimerContext( version: 0, @@ -167,14 +167,14 @@ import CoreFoundation while true { run() } } - func addSource(var rls: RunLoopSource, mode: NSString) { + func addSource(rls: RunLoopSource, mode: NSString) { rls.info.runLoops.append(self) CFRunLoopAddSource(cfRunLoop, unsafeBitCast(rls.cfObject, CFRunLoopSource.self), mode.cfString) CFRunLoopSourceSignal(unsafeBitCast(rls.cfObject, CFRunLoopSource.self)) CFRunLoopWakeUp(cfRunLoop) } - func addDelay(var rld: RunLoopDelay, mode: NSString) { + func addDelay(rld: RunLoopDelay, mode: NSString) { rld.info.runLoops.append(self) CFRunLoopAddTimer(cfRunLoop, unsafeBitCast(rld.cfObject, CFRunLoopTimer.self), mode.cfString) CFRunLoopWakeUp(cfRunLoop)