Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions ExecutionContext.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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 = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -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 */,
Expand Down Expand Up @@ -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 */,
Expand All @@ -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 */,
Expand All @@ -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 */,
Expand All @@ -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 */,
Expand Down
5 changes: 1 addition & 4 deletions ExecutionContext/ExecutionContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
//===----------------------------------------------------------------------===//

import Foundation
import CoreFoundation
import Result

public typealias Task = () throws -> Void
Expand Down Expand Up @@ -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
Expand Down
187 changes: 11 additions & 176 deletions ExecutionContext/PThreadExecutionContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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<pthread_t>
Expand All @@ -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<Void>) {
let runLoopSource = Unmanaged<RunLoopObject>.fromOpaque(COpaquePointer(rls)).takeUnretainedValue()
runLoopSource.cfObject = nil
runLoopSource.task()
}

private func sourceCancel(rls: UnsafeMutablePointer<Void>, rL: CFRunLoop!, mode:CFString!) {
let runLoopSource = Unmanaged<RunLoopObject>.fromOpaque(COpaquePointer(rls)).takeUnretainedValue()
runLoopSource.cfObject = nil
}

private func sourceRetain(rls: UnsafePointer<Void>) -> UnsafePointer<Void> {
Unmanaged<RunLoopObject>.fromOpaque(COpaquePointer(rls)).retain()
return rls
}

private func sourceRelease(rls: UnsafePointer<Void>) {
Unmanaged<RunLoopObject>.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<Void>(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<Void>) {
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<Void>(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)
Expand All @@ -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<ReturnType>(task:() throws -> ReturnType) throws -> ReturnType {
if rl === CFRunLoopGetCurrent() {
if rl.isCurrent() {
return try task()
} else {
return try syncThroughAsync(task)
Expand Down Expand Up @@ -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)
}

Expand Down
Loading