0001    //
0002    //  Platform.Linux.swift
0003    //  Rx
0004    //
0005    //  Created by Krunoslav Zaher on 12/29/15.
0006    //  Copyright © 2015 Krunoslav Zaher. All rights reserved.
0007    //
0008    
0009    #if os(Linux)
0010        ////////////////////////////////////////////////////////////////////////////////
0011        // This is not the greatest API in the world, this is just a tribute.
0012        // !!! Proof of concept until libdispatch becomes operational. !!!
0013        ////////////////////////////////////////////////////////////////////////////////
0014    
0015        import Foundation
0016        import XCTest
0017        import Glibc
0018        import SwiftShims
0019    
0020        // MARK: CoreFoundation run loop mock
0021    
0022        public typealias CFRunLoopRef = Int
0023        public let kCFRunLoopDefaultMode = "CFRunLoopDefaultMode"
0024    
0025        typealias Action = () -> ()
0026    
0027        var queue = Queue<Action>(capacity: 100)
0028    
0029        var runLoopCounter = 0
0030    
0031        extension NSThread {
0032            public var isMainThread: Bool {
0033                return true
0034            }
0035        }
0036    
0037        public func CFRunLoopWakeUp(runLoop: CFRunLoopRef) {
0038        }
0039    
0040        public func CFRunLoopStop(runLoop: CFRunLoopRef) {
0041            runLoopCounter -= 1
0042        }
0043    
0044        public func CFRunLoopPerformBlock(runLoop: CFRunLoopRef, _ mode: String, _ action: () -> ()) {
0045            queue.enqueue(action)
0046        }
0047    
0048        public func CFRunLoopRun() {
0049            runLoopCounter += 1
0050            let currentValueOfCounter = runLoopCounter
0051            while let front = queue.dequeue() {
0052                front()
0053                if runLoopCounter < currentValueOfCounter - 1 {
0054                    fatalError("called stop twice")
0055                }
0056    
0057                if runLoopCounter == currentValueOfCounter - 1 {
0058                    break
0059                }
0060            }
0061        }
0062    
0063        public func CFRunLoopGetCurrent() -> CFRunLoopRef {
0064            return 0
0065        }
0066    
0067        // MARK: Atomic, just something that works for single thread case
0068    
0069        #if TRACE_RESOURCES
0070        public typealias AtomicInt = Int64
0071        #else
0072        typealias AtomicInt = Int64
0073        #endif
0074    
0075        func AtomicIncrement(increment: UnsafeMutablePointer<AtomicInt>) -> AtomicInt {
0076            increment.memory = increment.memory + 1
0077            return increment.memory
0078        }
0079    
0080        func AtomicDecrement(increment: UnsafeMutablePointer<AtomicInt>) -> AtomicInt {
0081            increment.memory = increment.memory - 1
0082            return increment.memory
0083        }
0084    
0085        func AtomicCompareAndSwap(l: AtomicInt, _ r: AtomicInt, _ target: UnsafeMutablePointer<AtomicInt>) -> Bool {
0086            //return __sync_val_compare_and_swap(target, l, r)
0087            if target.memory == l {
0088                target.memory = r
0089                return true
0090            }
0091    
0092            return false
0093        }
0094    
0095        extension NSThread {
0096            static func setThreadLocalStorageValue<T: AnyObject>(value: T?, forKey key: String) {
0097                let currentThread = NSThread.currentThread()
0098                var threadDictionary = currentThread.threadDictionary
0099    
0100                if let newValue = value {
0101                    threadDictionary[key] = newValue
0102                }
0103                else {
0104                    threadDictionary[key] = nil
0105                }
0106    
0107                currentThread.threadDictionary = threadDictionary
0108            }
0109    
0110            static func getThreadLocalStorageValueForKey<T: AnyObject>(key: String) -> T? {
0111                let currentThread = NSThread.currentThread()
0112                let threadDictionary = currentThread.threadDictionary
0113    
0114                return threadDictionary[key] as? T
0115            }
0116        }
0117    
0118        //
0119    
0120        // MARK: objc mock
0121    
0122        public func objc_sync_enter(lock: AnyObject) {
0123        }
0124    
0125        public func objc_sync_exit(lock: AnyObject) {
0126    
0127        }
0128    
0129    
0130        // MARK: libdispatch
0131    
0132        public typealias dispatch_time_t = Int
0133        public typealias dispatch_source_t = Int
0134        public typealias dispatch_source_type_t = Int
0135        public typealias dispatch_queue_t = Int
0136        public typealias dispatch_object_t = Int
0137        public typealias dispatch_block_t = () -> ()
0138        public typealias dispatch_queue_attr_t = Int
0139        public typealias qos_class_t = Int
0140    
0141        public let DISPATCH_QUEUE_SERIAL = 0
0142    
0143        public let DISPATCH_QUEUE_PRIORITY_HIGH = 1
0144        public let DISPATCH_QUEUE_PRIORITY_DEFAULT = 2
0145        public let DISPATCH_QUEUE_PRIORITY_LOW = 3
0146    
0147        public let QOS_CLASS_USER_INTERACTIVE = 0
0148        public let QOS_CLASS_USER_INITIATED = 1
0149        public let QOS_CLASS_DEFAULT = 2
0150        public let QOS_CLASS_UTILITY = 3
0151        public let QOS_CLASS_BACKGROUND = 4
0152    
0153        public let DISPATCH_SOURCE_TYPE_TIMER = 0
0154        public let DISPATCH_TIME_FOREVER = 1 as UInt64
0155        public let NSEC_PER_SEC = 1
0156    
0157        public let DISPATCH_TIME_NOW = -1
0158    
0159        public func dispatch_time(when: dispatch_time_t, _ delta: Int64) -> dispatch_time_t {
0160            return when + Int(delta)
0161        }
0162    
0163        public func dispatch_queue_create(label: UnsafePointer<Int8>, _ attr: dispatch_queue_attr_t!) -> dispatch_queue_t! {
0164            return 0
0165        }
0166    
0167        public func dispatch_set_target_queue(object: dispatch_object_t!, _ queue: dispatch_queue_t!) {
0168        }
0169    
0170        public func dispatch_async(queue2: dispatch_queue_t, _ block: dispatch_block_t) {
0171            queue.enqueue(block)
0172        }
0173    
0174        public func dispatch_source_create(type: dispatch_source_type_t, _ handle: UInt, _ mask: UInt, _ queue: dispatch_queue_t!) -> dispatch_source_t! {
0175            return 0
0176        }
0177    
0178        public func dispatch_source_set_timer(source: dispatch_source_t, _ start: dispatch_time_t, _ interval: UInt64, _ leeway: UInt64) {
0179    
0180        }
0181    
0182        public func dispatch_source_set_event_handler(source: dispatch_source_t, _ handler: dispatch_block_t!) {
0183            queue.enqueue(handler)
0184        }
0185    
0186        public func dispatch_resume(object: dispatch_object_t) {
0187        }
0188    
0189        public func dispatch_source_cancel(source: dispatch_source_t) {
0190        }
0191    
0192        public func dispatch_get_global_queue(identifier: Int, _ flags: UInt) -> dispatch_queue_t! {
0193            return 0
0194        }
0195    
0196        public func dispatch_get_main_queue() -> dispatch_queue_t! {
0197            return 0
0198        }
0199    
0200        // MARK: XCTest
0201    
0202        public class Expectation {
0203            public func fulfill() {
0204            }
0205        }
0206    
0207        extension XCTestCase {
0208            public func setUp() {
0209            }
0210    
0211            public func tearDown() {
0212            }
0213    
0214            public func expectationWithDescription(description: String) -> Expectation {
0215                return Expectation()
0216            }
0217    
0218            public func waitForExpectationsWithTimeout(time: NSTimeInterval, action: ErrorType? -> Void) {
0219            }
0220        }
0221    
0222    #endif
0223