Skip to content

Commit dd005fc

Browse files
committed
Merge pull request #1 from kovpas/cfrunloop_ubuntu
Cfrunloop ubuntu
2 parents fc72c16 + a0e3e97 commit dd005fc

File tree

10 files changed

+321
-15
lines changed

10 files changed

+321
-15
lines changed

CoreFoundation/Base.subproj/CFRuntime.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -988,7 +988,7 @@ CF_PRIVATE Boolean __CFInitialized = 0;
988988
// move the next 2 lines down into the #if below, and make it static, after Foundation gets off this symbol on other platforms
989989
CF_EXPORT pthread_t _CFMainPThread;
990990
pthread_t _CFMainPThread = kNilPthreadT;
991-
#if DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_IPHONESIMULATOR
991+
#if DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_IPHONESIMULATOR || DEPLOYMENT_TARGET_LINUX
992992

993993
CF_EXPORT pthread_t _CF_pthread_main_thread_np(void);
994994
pthread_t _CF_pthread_main_thread_np(void) {

CoreFoundation/Base.subproj/CoreFoundation_Prefix.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,13 @@ CF_INLINE size_t malloc_size(void *memblock) {
221221
return malloc_usable_size(memblock);
222222
}
223223

224+
#include <time.h>
225+
CF_INLINE uint64_t mach_absolute_time() {
226+
struct timespec ts;
227+
clock_gettime(CLOCK_MONOTONIC, &ts);
228+
return (uint64_t)ts.tv_nsec + (uint64_t)ts.tv_sec * 1000000000UL;
229+
}
230+
224231
#endif
225232

226233
#if DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX

CoreFoundation/NumberDate.subproj/CFDate.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ const CFTimeInterval kCFAbsoluteTimeIntervalSince1904 = 3061152000.0L;
4343
CF_PRIVATE double __CFTSRRate = 0.0;
4444
static double __CF1_TSRRate = 0.0;
4545

46-
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_WINDOWS
46+
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
4747

4848
CF_PRIVATE uint64_t __CFTimeIntervalToTSR(CFTimeInterval ti) {
4949
if ((ti * __CFTSRRate) > INT64_MAX / 2) return (INT64_MAX / 2);
@@ -66,7 +66,7 @@ CF_PRIVATE CFTimeInterval __CFTimeIntervalUntilTSR(uint64_t tsr) {
6666

6767
// Technically this is 'TSR units' not a strict 'TSR' absolute time
6868
CF_PRIVATE uint64_t __CFTSRToNanoseconds(uint64_t tsr) {
69-
double tsrInNanoseconds = floor(tsr * __CF1_TSRRate * NSEC_PER_SEC);
69+
double tsrInNanoseconds = floor(tsr * __CF1_TSRRate * 1000000000UL);
7070
uint64_t ns = (uint64_t)tsrInNanoseconds;
7171
return ns;
7272
}

CoreFoundation/RunLoop.subproj/CFRunLoop.c

Lines changed: 198 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,18 @@ DISPATCH_EXPORT void _dispatch_main_queue_callback_4CF(void);
7171

7272
#define AbsoluteTime LARGE_INTEGER
7373

74+
#elif DEPLOYMENT_TARGET_LINUX
75+
#include <dlfcn.h>
76+
#include <poll.h>
77+
#include <sys/epoll.h>
78+
#include <sys/eventfd.h>
79+
#include <sys/timerfd.h>
80+
81+
#define _dispatch_get_main_queue_port_4CF dispatch_get_main_queue_eventfd_np
82+
#define _dispatch_main_queue_callback_4CF(x) dispatch_main_queue_drain_np()
7483
#endif
7584

76-
#if DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_IPHONESIMULATOR
85+
#if DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_IPHONESIMULATOR || DEPLOYMENT_TARGET_LINUX
7786
CF_EXPORT pthread_t _CF_pthread_main_thread_np(void);
7887
#define pthread_main_thread_np() _CF_pthread_main_thread_np()
7988
#endif
@@ -117,6 +126,13 @@ static pthread_t kNilPthreadT = { nil, nil };
117126
typedef int kern_return_t;
118127
#define KERN_SUCCESS 0
119128

129+
#elif DEPLOYMENT_TARGET_LINUX
130+
131+
static pthread_t kNilPthreadT = (pthread_t)0;
132+
#define pthreadPointer(a) ((void*)a)
133+
typedef int kern_return_t;
134+
#define KERN_SUCCESS 0
135+
120136
#else
121137

122138
static pthread_t kNilPthreadT = (pthread_t)0;
@@ -424,6 +440,50 @@ static kern_return_t __CFPortSetRemove(__CFPort port, __CFPortSet portSet) {
424440
return KERN_SUCCESS;
425441
}
426442

443+
#elif DEPLOYMENT_TARGET_LINUX
444+
// eventfd/timerfd descriptor
445+
typedef int __CFPort;
446+
#define CFPORT_NULL -1
447+
#define MACH_PORT_NULL CFPORT_NULL
448+
449+
// epoll file descriptor
450+
typedef int __CFPortSet;
451+
#define CFPORTSET_NULL -1
452+
453+
static __CFPort __CFPortAllocate(void) {
454+
return eventfd(0, EFD_CLOEXEC|EFD_NONBLOCK);
455+
}
456+
457+
CF_INLINE void __CFPortFree(__CFPort port) {
458+
close(port);
459+
}
460+
461+
CF_INLINE __CFPortSet __CFPortSetAllocate(void) {
462+
return epoll_create1(EPOLL_CLOEXEC);
463+
}
464+
465+
CF_INLINE kern_return_t __CFPortSetInsert(__CFPort port, __CFPortSet portSet) {
466+
if (CFPORT_NULL == port) {
467+
return -1;
468+
}
469+
struct epoll_event event;
470+
memset(&event, 0, sizeof(event));
471+
event.data.fd = port;
472+
event.events = EPOLLIN|EPOLLET;
473+
474+
return epoll_ctl(portSet, EPOLL_CTL_ADD, port, &event);
475+
}
476+
477+
CF_INLINE kern_return_t __CFPortSetRemove(__CFPort port, __CFPortSet portSet) {
478+
if (CFPORT_NULL == port) {
479+
return -1;
480+
}
481+
return epoll_ctl(portSet, EPOLL_CTL_DEL, port, NULL);
482+
}
483+
484+
CF_INLINE void __CFPortSetFree(__CFPortSet portSet) {
485+
close(portSet);
486+
}
427487
#endif
428488

429489
#if !defined(__MACTYPES__) && !defined(_OS_OSTYPES_H)
@@ -464,6 +524,36 @@ static uint32_t __CFSendTrivialMachMessage(mach_port_t port, uint32_t msg_id, CF
464524
if (result == MACH_SEND_TIMED_OUT) mach_msg_destroy(&header);
465525
return result;
466526
}
527+
#elif DEPLOYMENT_TARGET_LINUX
528+
529+
static int mk_timer_create(void) {
530+
return timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC);
531+
}
532+
533+
static kern_return_t mk_timer_destroy(int timer) {
534+
return close(timer);
535+
}
536+
537+
static kern_return_t mk_timer_arm(int timer, int64_t expire_time) {
538+
struct itimerspec ts;
539+
ts.it_value.tv_sec = expire_time / 1000000000UL;
540+
ts.it_value.tv_nsec = expire_time % 1000000000UL;
541+
542+
// Non-repeating timer
543+
ts.it_interval.tv_sec = 0;
544+
ts.it_interval.tv_nsec = 0;
545+
546+
return timerfd_settime(timer, TFD_TIMER_ABSTIME, &ts, NULL);
547+
}
548+
549+
static kern_return_t mk_timer_cancel(int timer, const void *unused) {
550+
return mk_timer_arm(timer, 0);
551+
}
552+
553+
CF_INLINE int64_t __CFUInt64ToAbsoluteTime(int64_t x) {
554+
return x;
555+
}
556+
467557
#elif DEPLOYMENT_TARGET_WINDOWS
468558

469559
static HANDLE mk_timer_create(void) {
@@ -547,7 +637,7 @@ struct __CFRunLoopMode {
547637
Boolean _dispatchTimerArmed;
548638
#endif
549639
#if USE_MK_TIMER_TOO
550-
mach_port_t _timerPort;
640+
__CFPort _timerPort;
551641
Boolean _mkTimerArmed;
552642
#endif
553643
#if DEPLOYMENT_TARGET_WINDOWS
@@ -2256,6 +2346,94 @@ static Boolean __CFRunLoopServiceMachPort(mach_port_name_t port, mach_msg_header
22562346
return false;
22572347
}
22582348

2349+
#elif DEPLOYMENT_TARGET_LINUX
2350+
2351+
#define TIMEOUT_INFINITY UINT64_MAX
2352+
2353+
static int __CFPollFileDescriptors(struct pollfd *fds, nfds_t nfds, uint64_t timeout) {
2354+
uint64_t elapsed = 0;
2355+
uint64_t start = mach_absolute_time();
2356+
int result = 0;
2357+
while (1) {
2358+
struct timespec ts = {0};
2359+
struct timespec *tsPtr = &ts;
2360+
if (timeout == TIMEOUT_INFINITY) {
2361+
tsPtr = NULL;
2362+
2363+
} else if (elapsed < timeout) {
2364+
uint64_t delta = timeout - elapsed;
2365+
ts.tv_sec = delta / 1000000000UL;
2366+
ts.tv_nsec = delta % 1000000000UL;
2367+
}
2368+
2369+
result = ppoll(fds, 1, tsPtr, NULL);
2370+
2371+
if (result == -1 && errno == EINTR) {
2372+
uint64_t end = mach_absolute_time();
2373+
elapsed += (end - start);
2374+
start = end;
2375+
2376+
} else {
2377+
return result;
2378+
}
2379+
}
2380+
}
2381+
2382+
// pass in either a portSet or onePort. portSet is an epollfd, onePort is either a timerfd or an eventfd.
2383+
// TODO: Better error handling. What should happen if we get an error on a file descriptor?
2384+
static Boolean __CFRunLoopServiceFileDescriptors(__CFPortSet portSet, __CFPort onePort, uint64_t timeout, int *livePort) {
2385+
struct pollfd fdInfo = {
2386+
.fd = (onePort == CFPORT_NULL) ? portSet : onePort,
2387+
.events = POLLIN
2388+
};
2389+
2390+
ssize_t result = __CFPollFileDescriptors(&fdInfo, 1, timeout);
2391+
if (result == 0)
2392+
return false;
2393+
2394+
CFAssert2(result != -1, __kCFLogAssertion, "%s(): error %d from ppoll", __PRETTY_FUNCTION__, errno);
2395+
2396+
int awokenFd;
2397+
2398+
if (onePort != CFPORT_NULL) {
2399+
CFAssert1(0 == (fdInfo.revents & (POLLERR|POLLHUP)), __kCFLogAssertion, "%s(): ppoll reported error for fd", __PRETTY_FUNCTION__);
2400+
awokenFd = onePort;
2401+
2402+
} else {
2403+
struct epoll_event event;
2404+
do {
2405+
result = epoll_wait(portSet, &event, 1 /*numEvents*/, 0 /*timeout*/);
2406+
} while (result == -1 && errno == EINTR);
2407+
CFAssert2(result >= 0, __kCFLogAssertion, "%s(): error %d from epoll_wait", __PRETTY_FUNCTION__, errno);
2408+
2409+
if (result == 0)
2410+
return false;
2411+
2412+
awokenFd = event.data.fd;
2413+
}
2414+
2415+
// Now we acknowledge the wakeup. awokenFd is an eventfd (or possibly a
2416+
// timerfd ?). In either case, we read an 8-byte integer, as per eventfd(2)
2417+
// and timerfd_create(2).
2418+
uint64_t value;
2419+
do {
2420+
result = read(awokenFd, &value, sizeof(value));
2421+
} while (result == -1 && errno == EINTR);
2422+
2423+
if (result == -1 && errno == EAGAIN) {
2424+
// Another thread stole the wakeup for this fd. (FIXME Can this actually
2425+
// happen?)
2426+
return false;
2427+
}
2428+
2429+
CFAssert2(result == sizeof(value), __kCFLogAssertion, "%s(): error %d from read(2) while acknowledging wakeup", __PRETTY_FUNCTION__, errno);
2430+
2431+
if (livePort)
2432+
*livePort = awokenFd;
2433+
2434+
return true;
2435+
}
2436+
22592437
#elif DEPLOYMENT_TARGET_WINDOWS
22602438

22612439
#define TIMEOUT_INFINITY INFINITE
@@ -2409,6 +2587,8 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter
24092587
#elif DEPLOYMENT_TARGET_WINDOWS
24102588
HANDLE livePort = NULL;
24112589
Boolean windowsMessageReceived = false;
2590+
#elif DEPLOYMENT_TARGET_LINUX
2591+
int livePort = -1;
24122592
#endif
24132593
__CFPortSet waitSet = rlm->_portSet;
24142594

@@ -2433,6 +2613,10 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter
24332613
if (__CFRunLoopServiceMachPort(dispatchPort, &msg, sizeof(msg_buffer), &livePort, 0, &voucherState, NULL)) {
24342614
goto handle_msg;
24352615
}
2616+
#elif DEPLOYMENT_TARGET_LINUX
2617+
if (__CFRunLoopServiceFileDescriptors(CFPORTSET_NULL, dispatchPort, 0, &livePort)) {
2618+
goto handle_msg;
2619+
}
24362620
#elif DEPLOYMENT_TARGET_WINDOWS
24372621
if (__CFRunLoopWaitForMultipleObjects(NULL, &dispatchPort, 0, 0, &livePort, NULL)) {
24382622
goto handle_msg;
@@ -2501,6 +2685,8 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter
25012685
#elif DEPLOYMENT_TARGET_WINDOWS
25022686
// Here, use the app-supplied message queue mask. They will set this if they are interested in having this run loop receive windows messages.
25032687
__CFRunLoopWaitForMultipleObjects(waitSet, NULL, poll ? 0 : TIMEOUT_INFINITY, rlm->_msgQMask, &livePort, &windowsMessageReceived);
2688+
#elif DEPLOYMENT_TARGET_LINUX
2689+
__CFRunLoopServiceFileDescriptors(waitSet, CFPORT_NULL, TIMEOUT_INFINITY, &livePort);
25042690
#endif
25052691

25062692
__CFRunLoopLock(rl);
@@ -2624,7 +2810,7 @@ static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInter
26242810
(void)mach_msg(reply, MACH_SEND_MSG, reply->msgh_size, 0, MACH_PORT_NULL, 0, MACH_PORT_NULL);
26252811
CFAllocatorDeallocate(kCFAllocatorSystemDefault, reply);
26262812
}
2627-
#elif DEPLOYMENT_TARGET_WINDOWS
2813+
#elif DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX
26282814
sourceHandledThisLoop = __CFRunLoopDoSource1(rl, rlm, rls) || sourceHandledThisLoop;
26292815
#endif
26302816
}
@@ -2740,6 +2926,13 @@ void CFRunLoopWakeUp(CFRunLoopRef rl) {
27402926
* wakeup pending, since the queue length is 1. */
27412927
ret = __CFSendTrivialMachMessage(rl->_wakeUpPort, 0, MACH_SEND_TIMEOUT, 0);
27422928
if (ret != MACH_MSG_SUCCESS && ret != MACH_SEND_TIMED_OUT) CRASH("*** Unable to send message to wake up port. (%d) ***", ret);
2929+
#elif DEPLOYMENT_TARGET_LINUX
2930+
int ret;
2931+
do {
2932+
ret = eventfd_write(rl->_wakeUpPort, 1);
2933+
} while (ret == -1 && errno == EINTR);
2934+
2935+
CFAssert1(0 == ret, __kCFLogAssertion, "%s(): Unable to send wake message to eventfd", __PRETTY_FUNCTION__);
27432936
#elif DEPLOYMENT_TARGET_WINDOWS
27442937
SetEvent(rl->_wakeUpPort);
27452938
#endif
@@ -3278,7 +3471,7 @@ static CFStringRef __CFRunLoopSourceCopyDescription(CFTypeRef cf) { /* DOES CALL
32783471
void *addr = rls->_context.version0.version == 0 ? (void *)rls->_context.version0.perform : (rls->_context.version0.version == 1 ? (void *)rls->_context.version1.perform : NULL);
32793472
#if DEPLOYMENT_TARGET_WINDOWS
32803473
contextDesc = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<CFRunLoopSource context>{version = %ld, info = %p, callout = %p}"), rls->_context.version0.version, rls->_context.version0.info, addr);
3281-
#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
3474+
#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX
32823475
Dl_info info;
32833476
const char *name = (dladdr(addr, &info) && info.dli_saddr == addr && info.dli_sname) ? info.dli_sname : "???";
32843477
contextDesc = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<CFRunLoopSource context>{version = %ld, info = %p, callout = %s (%p)}"), rls->_context.version0.version, rls->_context.version0.info, name, addr);
@@ -3479,7 +3672,7 @@ static CFStringRef __CFRunLoopObserverCopyDescription(CFTypeRef cf) { /* DOES CA
34793672
}
34803673
#if DEPLOYMENT_TARGET_WINDOWS
34813674
result = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("<CFRunLoopObserver %p [%p]>{valid = %s, activities = 0x%x, repeats = %s, order = %d, callout = %p, context = %@}"), cf, CFGetAllocator(rlo), __CFIsValid(rlo) ? "Yes" : "No", rlo->_activities, __CFRunLoopObserverRepeats(rlo) ? "Yes" : "No", rlo->_order, rlo->_callout, contextDesc);
3482-
#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
3675+
#elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_LINUX
34833676
void *addr = rlo->_callout;
34843677
Dl_info info;
34853678
const char *name = (dladdr(addr, &info) && info.dli_saddr == addr && info.dli_sname) ? info.dli_sname : "???";

Foundation.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@
200200
5BF7AEC01BCD51F9008F214A /* NSUUID.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BDC3F4B1BCC5DCB00ED97BB /* NSUUID.swift */; };
201201
5BF7AEC11BCD51F9008F214A /* NSValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BDC3F4C1BCC5DCB00ED97BB /* NSValue.swift */; };
202202
612952F91C1B235900BE0FD9 /* TestNSNull.swift in Sources */ = {isa = PBXBuildFile; fileRef = 612952F81C1B235900BE0FD9 /* TestNSNull.swift */; };
203+
61D6C9EF1C1DFE9500DEF583 /* TestNSTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61D6C9EE1C1DFE9500DEF583 /* TestNSTimer.swift */; };
203204
61E0117C1C1B554D000037DD /* TestNSRunLoop.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61E0117B1C1B554D000037DD /* TestNSRunLoop.swift */; };
204205
61E0117D1C1B5590000037DD /* NSRunLoop.swift in Sources */ = {isa = PBXBuildFile; fileRef = EADE0B761BD15DFF00C49C64 /* NSRunLoop.swift */; };
205206
61E0117E1C1B55B9000037DD /* NSTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BDC3F481BCC5DCB00ED97BB /* NSTimer.swift */; };
@@ -547,6 +548,7 @@
547548
5BF7AEC21BCD568D008F214A /* ForSwiftFoundationOnly.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ForSwiftFoundationOnly.h; sourceTree = "<group>"; };
548549
5EB6A15C1C188FC40037DCB8 /* TestNSJSONSerialization.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSJSONSerialization.swift; sourceTree = "<group>"; };
549550
612952F81C1B235900BE0FD9 /* TestNSNull.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSNull.swift; sourceTree = "<group>"; };
551+
61D6C9EE1C1DFE9500DEF583 /* TestNSTimer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSTimer.swift; sourceTree = "<group>"; };
550552
61E0117B1C1B554D000037DD /* TestNSRunLoop.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSRunLoop.swift; sourceTree = "<group>"; };
551553
61F8AE7C1C180FC600FB62F0 /* TestNSNotificationCenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSNotificationCenter.swift; sourceTree = "<group>"; };
552554
6E203B8C1C1303BB003B2576 /* TestNSBundle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSBundle.swift; sourceTree = "<group>"; };
@@ -1077,6 +1079,7 @@
10771079
5B40F9F11C125187000E72E3 /* TestNSXMLParser.swift */,
10781080
22B9C1E01C165D7A00DECFF9 /* TestNSDate.swift */,
10791081
DCDBB8321C1768AC00313299 /* TestNSData.swift */,
1082+
61D6C9EE1C1DFE9500DEF583 /* TestNSTimer.swift */,
10801083
84BA558D1C16F90900F48C54 /* TestNSTimeZone.swift */,
10811084
844DC3321C17584F005611F9 /* TestNSScanner.swift */,
10821085
83712C8D1C1684900049AD49 /* TestNSURLRequest.swift */,
@@ -1812,6 +1815,7 @@
18121815
EA66F64C1BF1619600136161 /* TestNSDictionary.swift in Sources */,
18131816
ED58F76F1C134B3A00E6A5BE /* (null) in Sources */,
18141817
EA66F6581BF1619600136161 /* TestNSURL.swift in Sources */,
1818+
61D6C9EF1C1DFE9500DEF583 /* TestNSTimer.swift in Sources */,
18151819
61E0117C1C1B554D000037DD /* TestNSRunLoop.swift in Sources */,
18161820
EA66F6441BF1619600136161 /* main.swift in Sources */,
18171821
);

Foundation/NSRunLoop.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,12 @@ extension NSRunLoop {
7171
}
7272

7373
public func runMode(mode: String, beforeDate limitDate: NSDate) -> Bool {
74-
let result: Int32 = CFRunLoopRunSpecific(_cfObject, mode._cfObject, limitDate.timeIntervalSinceNow, false)
75-
let runloopResult = CFRunLoopRunResult(rawValue: result)
74+
let runloopResult = CFRunLoopRunInMode(mode._cfObject, limitDate.timeIntervalSinceNow, false)
75+
#if os(Linux)
76+
return runloopResult == 2 || runloopResult == 3
77+
#else
7678
return runloopResult == .HandledSource || runloopResult == .TimedOut
79+
#endif
7780
}
7881

7982
}

Foundation/NSSwiftRuntime.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ internal func __CFInitializeSwift() {
121121
// _CFRuntimeBridgeTypeToClass(CFAttributedStringGetTypeID(), unsafeBitCast(NSMutableAttributedString.self, UnsafePointer<Void>.self))
122122
// _CFRuntimeBridgeTypeToClass(CFReadStreamGetTypeID(), unsafeBitCast(NSInputStream.self, UnsafePointer<Void>.self))
123123
// _CFRuntimeBridgeTypeToClass(CFWriteStreamGetTypeID(), unsafeBitCast(NSOutputStream.self, UnsafePointer<Void>.self))
124-
// _CFRuntimeBridgeTypeToClass(CFRunLoopTimerGetTypeID(), unsafeBitCast(NSTimer.self, UnsafePointer<Void>.self))
124+
_CFRuntimeBridgeTypeToClass(CFRunLoopTimerGetTypeID(), unsafeBitCast(NSTimer.self, UnsafePointer<Void>.self))
125125

126126
__CFSwiftBridge.NSObject.isEqual = _CFSwiftIsEqual
127127
__CFSwiftBridge.NSObject.hash = _CFSwiftGetHash

0 commit comments

Comments
 (0)