Merge pull request #1439 from millenomi/cfrunloop-fix-linux

diff --git a/Foundation/RunLoop.swift b/Foundation/RunLoop.swift
index ce4cf81..522664f 100644
--- a/Foundation/RunLoop.swift
+++ b/Foundation/RunLoop.swift
@@ -43,6 +43,17 @@
 extension RunLoopMode {
     public static let defaultRunLoopMode = RunLoopMode("kCFRunLoopDefaultMode")
     public static let commonModes = RunLoopMode("kCFRunLoopCommonModes")
+    
+    // Use this instead of .rawValue._cfObject; this will allow CFRunLoop to use pointer equality internally.
+    fileprivate var _cfStringUniquingKnown: CFString {
+        if self == .defaultRunLoopMode {
+            return kCFRunLoopDefaultMode
+        } else if self == .commonModes {
+            return kCFRunLoopCommonModes
+        } else {
+            return rawValue._cfObject
+        }
+    }
 }
 
 internal func _NSRunLoopNew(_ cf: CFRunLoop) -> Unmanaged<AnyObject> {
@@ -81,7 +92,7 @@
     }
 
     open func add(_ timer: Timer, forMode mode: RunLoopMode) {
-        CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer._cfObject, mode.rawValue._cfObject)
+        CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer._cfObject, mode._cfStringUniquingKnown)
     }
 
     open func add(_ aPort: Port, forMode mode: RunLoopMode) {
@@ -135,7 +146,7 @@
         if _cfRunLoop !== CFRunLoopGetCurrent() {
             return false
         }
-        let modeArg = mode.rawValue._cfObject
+        let modeArg = mode._cfStringUniquingKnown
         if _CFRunLoopFinished(_cfRunLoop, modeArg) {
             return false
         }
@@ -147,7 +158,7 @@
     }
 
     public func perform(inModes modes: [RunLoopMode], block: @escaping () -> Void) {
-        CFRunLoopPerformBlock(getCFRunLoop(), (modes.map { $0.rawValue._nsObject })._cfObject, block)
+        CFRunLoopPerformBlock(getCFRunLoop(), (modes.map { $0._cfStringUniquingKnown })._cfObject, block)
     }
     
     public func perform(_ block: @escaping () -> Void) {
diff --git a/TestFoundation/TestRunLoop.swift b/TestFoundation/TestRunLoop.swift
index 27668a2..931af8d 100644
--- a/TestFoundation/TestRunLoop.swift
+++ b/TestFoundation/TestRunLoop.swift
@@ -21,6 +21,7 @@
         return [
             ("test_constants", test_constants),
             ("test_runLoopInit", test_runLoopInit),
+            ("test_commonModes", test_commonModes),
             // these tests do not work the same as Darwin https://bugs.swift.org/browse/SR-399
 //            ("test_runLoopRunMode", test_runLoopRunMode),
 //            ("test_runLoopLimitDate", test_runLoopLimitDate),
@@ -90,4 +91,16 @@
         
         XCTAssertLessThan(abs(timerTickInterval - expectedTimeInterval), 0.01)
     }
+    
+    func test_commonModes() {
+        let runLoop = RunLoop.current
+        let done = expectation(description: "The timer has fired")
+        let timer = Timer(timeInterval: 1, repeats: false) { (_) in
+            done.fulfill()
+        }
+        
+        runLoop.add(timer, forMode: .commonModes)
+        
+        waitForExpectations(timeout: 10)
+    }
 }