2 * Copyright (c) 2008 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 Copyright 1998-2002, Apple, Inc. All rights reserved.
25 Responsibility: Christopher Kane
28 #if (DEPLOYMENT_TARGET_MACOSX) || defined(__WIN32__)
30 #include <CoreFoundation/CFRunLoop.h>
31 #include <CoreFoundation/CFSet.h>
32 #include <CoreFoundation/CFBag.h>
33 #include "CFInternal.h"
37 #if DEPLOYMENT_TARGET_MACOSX
38 #include <mach/mach.h>
39 #include <mach/clock_types.h>
40 #include <mach/clock.h>
44 #if !defined(__MINGW32__) && !defined(__CYGWIN__)
45 // With the MS headers, turning off Standard-C gets you macros for stat vs _stat.
46 // Strictly speaking, this is supposed to control traditional vs ANSI C features.
52 #if !defined(__MINGW32__) && !defined(__CYGWIN__)
57 static int _LogCFRunLoop
= 0;
60 static pthread_t kNilPthreadT
= { nil
, nil
};
61 #define pthreadPointer(a) a.p
62 #define lockCount(a) a.LockCount
64 static pthread_t kNilPthreadT
= (pthread_t
)0;
65 #define pthreadPointer(a) a
66 #define lockCount(a) a
70 #if DEPLOYMENT_TARGET_MACOSX
71 #include <sys/types.h>
72 #include <sys/event.h>
77 const void *(*retain
)(const void *info
);
78 void (*release
)(const void *info
);
79 CFStringRef (*copyDescription
)(const void *info
);
80 Boolean (*equal
)(const void *info1
, const void *info2
);
81 CFHashCode (*hash
)(const void *info
);
82 void (*perform
)(const struct kevent
*kev
, void *info
);
84 } CFRunLoopSourceContext2
;
86 // The bits in the flags field in the kevent structure are cleared except for EV_ONESHOT and EV_CLEAR.
87 // Do not use the udata field of the kevent structure -- that field is smashed by CFRunLoop.
88 // There is no way to EV_ENABLE or EV_DISABLE a kevent.
89 // The "autoinvalidation" of EV_ONESHOT is not handled properly by CFRunLoop yet.
90 // The "autoinvalidation" of EV_DELETE on the last close of a file descriptor is not handled properly by CFRunLoop yet.
91 // There is no way to reset the state in a kevent (such as clearing the EV_EOF state for fifos).
94 extern bool CFDictionaryGetKeyIfPresent(CFDictionaryRef dict
, const void *key
, const void **actualkey
);
96 // In order to reuse most of the code across Mach and Windows v1 RunLoopSources, we define a
97 // simple abstraction layer spanning Mach ports and Windows HANDLES
98 #if DEPLOYMENT_TARGET_MACOSX
100 typedef mach_port_t __CFPort
;
101 #define CFPORT_NULL MACH_PORT_NULL
102 typedef mach_port_t __CFPortSet
;
104 static __CFPort
__CFPortAllocate(void) {
107 ret
= mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE
, &result
);
108 if (KERN_SUCCESS
== ret
) {
109 ret
= mach_port_insert_right(mach_task_self(), result
, result
, MACH_MSG_TYPE_MAKE_SEND
);
111 if (KERN_SUCCESS
== ret
) {
112 mach_port_limits_t limits
;
113 limits
.mpl_qlimit
= 1;
114 ret
= mach_port_set_attributes(mach_task_self(), result
, MACH_PORT_LIMITS_INFO
, (mach_port_info_t
)&limits
, MACH_PORT_LIMITS_INFO_COUNT
);
116 return (KERN_SUCCESS
== ret
) ? result
: CFPORT_NULL
;
119 CF_INLINE
void __CFPortFree(__CFPort port
) {
120 mach_port_destroy(mach_task_self(), port
);
123 CF_INLINE __CFPortSet
__CFPortSetAllocate(void) {
125 kern_return_t ret
= mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_PORT_SET
, &result
);
126 return (KERN_SUCCESS
== ret
) ? result
: CFPORT_NULL
;
129 CF_INLINE Boolean
__CFPortSetInsert(__CFPort port
, __CFPortSet portSet
) {
130 kern_return_t ret
= mach_port_insert_member(mach_task_self(), port
, portSet
);
131 return (KERN_SUCCESS
== ret
);
134 CF_INLINE Boolean
__CFPortSetRemove(__CFPort port
, __CFPortSet portSet
) {
135 kern_return_t ret
= mach_port_extract_member(mach_task_self(), port
, portSet
);
136 return (KERN_SUCCESS
== ret
);
139 CF_INLINE
void __CFPortSetFree(__CFPortSet portSet
) {
141 mach_port_name_array_t array
;
142 mach_msg_type_number_t idx
, number
;
144 ret
= mach_port_get_set_status(mach_task_self(), portSet
, &array
, &number
);
145 if (KERN_SUCCESS
== ret
) {
146 for (idx
= 0; idx
< number
; idx
++) {
147 mach_port_extract_member(mach_task_self(), array
[idx
], portSet
);
149 vm_deallocate(mach_task_self(), (vm_address_t
)array
, number
* sizeof(mach_port_name_t
));
151 mach_port_destroy(mach_task_self(), portSet
);
154 #elif defined(__WIN32__)
156 typedef HANDLE __CFPort
;
157 #define CFPORT_NULL NULL
159 // A simple dynamic array of HANDLEs, which grows to a high-water mark
160 typedef struct ___CFPortSet
{
164 CFSpinLock_t lock
; // insert and remove must be thread safe, like the Mach calls
167 CF_INLINE __CFPort
__CFPortAllocate(void) {
168 return CreateEvent(NULL
, true, false, NULL
);
171 CF_INLINE
void __CFPortFree(__CFPort port
) {
175 static __CFPortSet
__CFPortSetAllocate(void) {
176 __CFPortSet result
= CFAllocatorAllocate(kCFAllocatorSystemDefault
, sizeof(struct ___CFPortSet
), 0);
179 result
->handles
= CFAllocatorAllocate(kCFAllocatorSystemDefault
, result
->size
* sizeof(HANDLE
), 0);
180 CF_SPINLOCK_INIT_FOR_STRUCTS(result
->lock
);
184 static void __CFPortSetFree(__CFPortSet portSet
) {
185 CFAllocatorDeallocate(kCFAllocatorSystemDefault
, portSet
->handles
);
186 CFAllocatorDeallocate(kCFAllocatorSystemDefault
, portSet
);
189 // Returns portBuf if ports fit in that space, else returns another ptr that must be freed
190 static __CFPort
*__CFPortSetGetPorts(__CFPortSet portSet
, __CFPort
*portBuf
, uint32_t bufSize
, uint32_t *portsUsed
) {
191 __CFSpinLock(&(portSet
->lock
));
192 __CFPort
*result
= portBuf
;
193 if (bufSize
> portSet
->used
)
194 result
= CFAllocatorAllocate(kCFAllocatorSystemDefault
, portSet
->used
* sizeof(HANDLE
), 0);
195 memmove(result
, portSet
->handles
, portSet
->used
* sizeof(HANDLE
));
196 *portsUsed
= portSet
->used
;
197 __CFSpinUnlock(&(portSet
->lock
));
201 static Boolean
__CFPortSetInsert(__CFPort port
, __CFPortSet portSet
) {
202 __CFSpinLock(&(portSet
->lock
));
203 if (portSet
->used
>= portSet
->size
) {
205 portSet
->handles
= CFAllocatorReallocate(kCFAllocatorSystemDefault
, portSet
->handles
, portSet
->size
* sizeof(HANDLE
), 0);
207 if (portSet
->used
>= MAXIMUM_WAIT_OBJECTS
)
208 CFLog(kCFLogLevelWarning
, CFSTR("*** More than MAXIMUM_WAIT_OBJECTS (%d) ports add to a port set. The last ones will be ignored."), MAXIMUM_WAIT_OBJECTS
);
209 portSet
->handles
[portSet
->used
++] = port
;
210 __CFSpinUnlock(&(portSet
->lock
));
214 static Boolean
__CFPortSetRemove(__CFPort port
, __CFPortSet portSet
) {
216 __CFSpinLock(&(portSet
->lock
));
217 for (i
= 0; i
< portSet
->used
; i
++) {
218 if (portSet
->handles
[i
] == port
) {
219 for (j
= i
+1; j
< portSet
->used
; j
++) {
220 portSet
->handles
[j
-1] = portSet
->handles
[j
];
223 __CFSpinUnlock(&(portSet
->lock
));
227 __CFSpinUnlock(&(portSet
->lock
));
233 #if DEPLOYMENT_TARGET_MACOSX
234 extern mach_port_name_t
mk_timer_create(void);
235 extern kern_return_t
mk_timer_destroy(mach_port_name_t name
);
236 extern kern_return_t
mk_timer_arm(mach_port_name_t name
, AbsoluteTime expire_time
);
237 extern kern_return_t
mk_timer_cancel(mach_port_name_t name
, AbsoluteTime
*result_time
);
239 CF_INLINE AbsoluteTime
__CFUInt64ToAbsoluteTime(int64_t x
) {
242 a
.lo
= x
& (int64_t)0xFFFFFFFF;
246 static uint32_t __CFSendTrivialMachMessage(mach_port_t port
, uint32_t msg_id
, CFOptionFlags options
, uint32_t timeout
) {
247 kern_return_t result
;
248 mach_msg_header_t header
;
249 header
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
, 0);
250 header
.msgh_size
= sizeof(mach_msg_header_t
);
251 header
.msgh_remote_port
= port
;
252 header
.msgh_local_port
= MACH_PORT_NULL
;
253 header
.msgh_id
= msg_id
;
254 result
= mach_msg(&header
, MACH_SEND_MSG
|options
, header
.msgh_size
, 0, MACH_PORT_NULL
, timeout
, MACH_PORT_NULL
);
255 if (result
== MACH_SEND_TIMED_OUT
) mach_msg_destroy(&header
);
260 /* unlock a run loop and modes before doing callouts/sleeping */
261 /* never try to take the run loop lock with a mode locked */
262 /* be very careful of common subexpression elimination and compacting code, particular across locks and unlocks! */
263 /* run loop mode structures should never be deallocated, even if they become empty */
265 static CFTypeID __kCFRunLoopModeTypeID
= _kCFRuntimeNotATypeID
;
266 static CFTypeID __kCFRunLoopTypeID
= _kCFRuntimeNotATypeID
;
267 static CFTypeID __kCFRunLoopSourceTypeID
= _kCFRuntimeNotATypeID
;
268 static CFTypeID __kCFRunLoopObserverTypeID
= _kCFRuntimeNotATypeID
;
269 static CFTypeID __kCFRunLoopTimerTypeID
= _kCFRuntimeNotATypeID
;
271 typedef struct __CFRunLoopMode
*CFRunLoopModeRef
;
273 struct __CFRunLoopMode
{
275 CFSpinLock_t _lock
; /* must have the run loop locked before locking this */
279 CFMutableSetRef _sources
;
280 CFMutableSetRef _observers
;
281 CFMutableSetRef _timers
;
282 CFMutableArrayRef _submodes
; // names of the submodes
283 __CFPortSet _portSet
;
284 #if DEPLOYMENT_TARGET_MACOSX
289 static int64_t __CFRunLoopGetNextTimerFireTSR(CFRunLoopRef rl
, CFRunLoopModeRef rlm
);
291 CF_INLINE
void __CFRunLoopModeLock(CFRunLoopModeRef rlm
) {
292 __CFSpinLock(&(rlm
->_lock
));
295 CF_INLINE
void __CFRunLoopModeUnlock(CFRunLoopModeRef rlm
) {
296 __CFSpinUnlock(&(rlm
->_lock
));
299 static Boolean
__CFRunLoopModeEqual(CFTypeRef cf1
, CFTypeRef cf2
) {
300 CFRunLoopModeRef rlm1
= (CFRunLoopModeRef
)cf1
;
301 CFRunLoopModeRef rlm2
= (CFRunLoopModeRef
)cf2
;
302 return CFEqual(rlm1
->_name
, rlm2
->_name
);
305 static CFHashCode
__CFRunLoopModeHash(CFTypeRef cf
) {
306 CFRunLoopModeRef rlm
= (CFRunLoopModeRef
)cf
;
307 return CFHash(rlm
->_name
);
310 static CFStringRef
__CFRunLoopModeCopyDescription(CFTypeRef cf
) {
311 CFRunLoopModeRef rlm
= (CFRunLoopModeRef
)cf
;
312 CFMutableStringRef result
;
313 result
= CFStringCreateMutable(kCFAllocatorSystemDefault
, 0);
314 CFStringAppendFormat(result
, NULL
, CFSTR("<CFRunLoopMode %p [%p]>{name = %@, locked = %s, "), rlm
, CFGetAllocator(rlm
), rlm
->_name
, lockCount(rlm
->_lock
) ? "true" : "false");
315 CFStringAppendFormat(result
, NULL
, CFSTR("port set = %p,"), rlm
->_portSet
);
316 CFStringAppendFormat(result
, NULL
, CFSTR("\n\tsources = %@,\n\tobservers == %@,\n\ttimers = %@\n},\n"), rlm
->_sources
, rlm
->_observers
, rlm
->_timers
);
320 static void __CFRunLoopModeDeallocate(CFTypeRef cf
) {
321 CFRunLoopModeRef rlm
= (CFRunLoopModeRef
)cf
;
322 if (NULL
!= rlm
->_sources
) CFRelease(rlm
->_sources
);
323 if (NULL
!= rlm
->_observers
) CFRelease(rlm
->_observers
);
324 if (NULL
!= rlm
->_timers
) CFRelease(rlm
->_timers
);
325 if (NULL
!= rlm
->_submodes
) CFRelease(rlm
->_submodes
);
326 CFRelease(rlm
->_name
);
327 __CFPortSetFree(rlm
->_portSet
);
328 #if DEPLOYMENT_TARGET_MACOSX
329 if (-1 != rlm
->_kq
) close(rlm
->_kq
);
335 CFSpinLock_t _lock
; /* locked for accessing mode list */
336 __CFPort _wakeUpPort
; // used for CFRunLoopWakeUp
337 volatile uint32_t *_stopped
;
338 CFMutableSetRef _commonModes
;
339 CFMutableSetRef _commonModeItems
;
340 CFRunLoopModeRef _currentMode
;
341 CFMutableSetRef _modes
;
345 /* Bit 0 of the base reserved bits is used for stopped state */
346 /* Bit 1 of the base reserved bits is used for sleeping state */
347 /* Bit 2 of the base reserved bits is used for deallocating state */
349 CF_INLINE Boolean
__CFRunLoopIsStopped(CFRunLoopRef rl
) {
350 return (rl
->_stopped
&& rl
->_stopped
[2]) ? true : false;
353 CF_INLINE
void __CFRunLoopSetStopped(CFRunLoopRef rl
) {
354 if (rl
->_stopped
) rl
->_stopped
[2] = 0x53544F50; // 'STOP'
357 CF_INLINE
void __CFRunLoopUnsetStopped(CFRunLoopRef rl
) {
358 if (rl
->_stopped
) rl
->_stopped
[2] = 0x0;
361 CF_INLINE Boolean
__CFRunLoopIsSleeping(CFRunLoopRef rl
) {
362 return (Boolean
)__CFBitfieldGetValue(((const CFRuntimeBase
*)rl
)->_cfinfo
[CF_INFO_BITS
], 1, 1);
365 CF_INLINE
void __CFRunLoopSetSleeping(CFRunLoopRef rl
) {
366 __CFBitfieldSetValue(((CFRuntimeBase
*)rl
)->_cfinfo
[CF_INFO_BITS
], 1, 1, 1);
369 CF_INLINE
void __CFRunLoopUnsetSleeping(CFRunLoopRef rl
) {
370 __CFBitfieldSetValue(((CFRuntimeBase
*)rl
)->_cfinfo
[CF_INFO_BITS
], 1, 1, 0);
373 CF_INLINE Boolean
__CFRunLoopIsDeallocating(CFRunLoopRef rl
) {
374 return (Boolean
)__CFBitfieldGetValue(((const CFRuntimeBase
*)rl
)->_cfinfo
[CF_INFO_BITS
], 2, 2);
377 CF_INLINE
void __CFRunLoopSetDeallocating(CFRunLoopRef rl
) {
378 __CFBitfieldSetValue(((CFRuntimeBase
*)rl
)->_cfinfo
[CF_INFO_BITS
], 2, 2, 1);
381 CF_INLINE
void __CFRunLoopLock(CFRunLoopRef rl
) {
382 __CFSpinLock(&(((CFRunLoopRef
)rl
)->_lock
));
385 CF_INLINE
void __CFRunLoopUnlock(CFRunLoopRef rl
) {
386 __CFSpinUnlock(&(((CFRunLoopRef
)rl
)->_lock
));
389 static CFStringRef
__CFRunLoopCopyDescription(CFTypeRef cf
) {
390 CFRunLoopRef rl
= (CFRunLoopRef
)cf
;
391 CFMutableStringRef result
;
392 result
= CFStringCreateMutable(kCFAllocatorSystemDefault
, 0);
393 CFStringAppendFormat(result
, NULL
, CFSTR("<CFRunLoop %p [%p]>{locked = %s, wait port = 0x%x, stopped = %s,\ncurrent mode = %@,\n"), cf
, CFGetAllocator(cf
), lockCount(rl
->_lock
) ? "true" : "false", rl
->_wakeUpPort
, (rl
->_stopped
&& (rl
->_stopped
[2] == 0x53544F50)) ? "true" : "false", rl
->_currentMode
? rl
->_currentMode
->_name
: CFSTR("(none)"));
394 CFStringAppendFormat(result
, NULL
, CFSTR("common modes = %@,\ncommon mode items = %@,\nmodes = %@}\n"), rl
->_commonModes
, rl
->_commonModeItems
, rl
->_modes
);
398 /* call with rl locked */
399 static CFRunLoopModeRef
__CFRunLoopFindMode(CFRunLoopRef rl
, CFStringRef modeName
, Boolean create
) {
401 CFRunLoopModeRef rlm
;
402 struct __CFRunLoopMode srlm
;
403 srlm
._base
._cfisa
= __CFISAForTypeID(__kCFRunLoopModeTypeID
);
404 srlm
._base
._cfinfo
[CF_INFO_BITS
] = 0;
405 _CFRuntimeSetInstanceTypeID(&srlm
, __kCFRunLoopModeTypeID
);
406 srlm
._name
= modeName
;
407 rlm
= (CFRunLoopModeRef
)CFSetGetValue(rl
->_modes
, &srlm
);
409 __CFRunLoopModeLock(rlm
);
415 rlm
= (CFRunLoopModeRef
)_CFRuntimeCreateInstance(CFGetAllocator(rl
), __kCFRunLoopModeTypeID
, sizeof(struct __CFRunLoopMode
) - sizeof(CFRuntimeBase
), NULL
);
419 CF_SPINLOCK_INIT_FOR_STRUCTS(rlm
->_lock
);
420 rlm
->_name
= CFStringCreateCopy(CFGetAllocator(rlm
), modeName
);
421 rlm
->_stopped
= false;
422 rlm
->_sources
= NULL
;
423 rlm
->_observers
= NULL
;
425 rlm
->_submodes
= NULL
;
426 rlm
->_portSet
= __CFPortSetAllocate();
427 if (CFPORT_NULL
== rlm
->_portSet
) HALT
;
428 if (!__CFPortSetInsert(rl
->_wakeUpPort
, rlm
->_portSet
)) HALT
;
429 #if DEPLOYMENT_TARGET_MACOSX
432 CFSetAddValue(rl
->_modes
, rlm
);
434 __CFRunLoopModeLock(rlm
); /* return mode locked */
439 // expects rl and rlm locked
440 static Boolean
__CFRunLoopModeIsEmpty(CFRunLoopRef rl
, CFRunLoopModeRef rlm
) {
442 if (NULL
== rlm
) return true;
443 if (NULL
!= rlm
->_sources
&& 0 < CFSetGetCount(rlm
->_sources
)) return false;
444 if (NULL
!= rlm
->_timers
&& 0 < CFSetGetCount(rlm
->_timers
)) return false;
445 if (NULL
!= rlm
->_submodes
) {
447 for (idx
= 0, cnt
= CFArrayGetCount(rlm
->_submodes
); idx
< cnt
; idx
++) {
448 CFStringRef modeName
= (CFStringRef
)CFArrayGetValueAtIndex(rlm
->_submodes
, idx
);
449 CFRunLoopModeRef subrlm
;
451 subrlm
= __CFRunLoopFindMode(rl
, modeName
, false);
452 subIsEmpty
= (NULL
!= subrlm
) ? __CFRunLoopModeIsEmpty(rl
, subrlm
) : true;
453 if (NULL
!= subrlm
) __CFRunLoopModeUnlock(subrlm
);
454 if (!subIsEmpty
) return false;
460 /* Bit 3 in the base reserved bits is used for invalid state in run loop objects */
462 CF_INLINE Boolean
__CFIsValid(const void *cf
) {
463 return (Boolean
)__CFBitfieldGetValue(((const CFRuntimeBase
*)cf
)->_cfinfo
[CF_INFO_BITS
], 3, 3);
466 CF_INLINE
void __CFSetValid(void *cf
) {
467 __CFBitfieldSetValue(((CFRuntimeBase
*)cf
)->_cfinfo
[CF_INFO_BITS
], 3, 3, 1);
470 CF_INLINE
void __CFUnsetValid(void *cf
) {
471 __CFBitfieldSetValue(((CFRuntimeBase
*)cf
)->_cfinfo
[CF_INFO_BITS
], 3, 3, 0);
474 struct __CFRunLoopSource
{
478 CFIndex _order
; /* immutable */
479 CFMutableBagRef _runLoops
;
481 CFRunLoopSourceContext version0
; /* immutable, except invalidation */
482 CFRunLoopSourceContext1 version1
; /* immutable, except invalidation */
486 /* Bit 1 of the base reserved bits is used for signalled state */
488 CF_INLINE Boolean
__CFRunLoopSourceIsSignaled(CFRunLoopSourceRef rls
) {
489 return (Boolean
)__CFBitfieldGetValue(rls
->_bits
, 1, 1);
492 CF_INLINE
void __CFRunLoopSourceSetSignaled(CFRunLoopSourceRef rls
) {
493 __CFBitfieldSetValue(rls
->_bits
, 1, 1, 1);
496 CF_INLINE
void __CFRunLoopSourceUnsetSignaled(CFRunLoopSourceRef rls
) {
497 __CFBitfieldSetValue(rls
->_bits
, 1, 1, 0);
500 CF_INLINE
void __CFRunLoopSourceLock(CFRunLoopSourceRef rls
) {
501 __CFSpinLock(&(rls
->_lock
));
504 CF_INLINE
void __CFRunLoopSourceUnlock(CFRunLoopSourceRef rls
) {
505 __CFSpinUnlock(&(rls
->_lock
));
508 /* rlm is not locked */
509 static void __CFRunLoopSourceSchedule(CFRunLoopSourceRef rls
, CFRunLoopRef rl
, CFRunLoopModeRef rlm
) { /* DOES CALLOUT */
510 __CFRunLoopSourceLock(rls
);
511 if (NULL
== rls
->_runLoops
) {
512 rls
->_runLoops
= CFBagCreateMutable(kCFAllocatorSystemDefault
, 0, NULL
);
514 CFBagAddValue(rls
->_runLoops
, rl
);
515 __CFRunLoopSourceUnlock(rls
); // have to unlock before the callout -- cannot help clients with safety
516 if (0 == rls
->_context
.version0
.version
) {
517 if (NULL
!= rls
->_context
.version0
.schedule
) {
518 rls
->_context
.version0
.schedule(rls
->_context
.version0
.info
, rl
, rlm
->_name
);
520 } else if (1 == rls
->_context
.version0
.version
) {
521 __CFPort port
= rls
->_context
.version1
.getPort(rls
->_context
.version1
.info
); /* CALLOUT */
522 if (CFPORT_NULL
!= port
) {
523 __CFPortSetInsert(port
, rlm
->_portSet
);
528 /* rlm is not locked */
529 static void __CFRunLoopSourceCancel(CFRunLoopSourceRef rls
, CFRunLoopRef rl
, CFRunLoopModeRef rlm
) { /* DOES CALLOUT */
530 if (0 == rls
->_context
.version0
.version
) {
531 if (NULL
!= rls
->_context
.version0
.cancel
) {
532 rls
->_context
.version0
.cancel(rls
->_context
.version0
.info
, rl
, rlm
->_name
); /* CALLOUT */
534 } else if (1 == rls
->_context
.version0
.version
) {
535 __CFPort port
= rls
->_context
.version1
.getPort(rls
->_context
.version1
.info
); /* CALLOUT */
536 if (CFPORT_NULL
!= port
) {
537 __CFPortSetRemove(port
, rlm
->_portSet
);
540 __CFRunLoopSourceLock(rls
);
541 if (NULL
!= rls
->_runLoops
) {
542 CFBagRemoveValue(rls
->_runLoops
, rl
);
544 __CFRunLoopSourceUnlock(rls
);
547 struct __CFRunLoopObserver
{
550 CFRunLoopRef _runLoop
;
552 CFOptionFlags _activities
; /* immutable */
553 CFIndex _order
; /* immutable */
554 CFRunLoopObserverCallBack _callout
; /* immutable */
555 CFRunLoopObserverContext _context
; /* immutable, except invalidation */
558 /* Bit 0 of the base reserved bits is used for firing state */
559 /* Bit 1 of the base reserved bits is used for repeats state */
561 CF_INLINE Boolean
__CFRunLoopObserverIsFiring(CFRunLoopObserverRef rlo
) {
562 return (Boolean
)__CFBitfieldGetValue(((const CFRuntimeBase
*)rlo
)->_cfinfo
[CF_INFO_BITS
], 0, 0);
565 CF_INLINE
void __CFRunLoopObserverSetFiring(CFRunLoopObserverRef rlo
) {
566 __CFBitfieldSetValue(((CFRuntimeBase
*)rlo
)->_cfinfo
[CF_INFO_BITS
], 0, 0, 1);
569 CF_INLINE
void __CFRunLoopObserverUnsetFiring(CFRunLoopObserverRef rlo
) {
570 __CFBitfieldSetValue(((CFRuntimeBase
*)rlo
)->_cfinfo
[CF_INFO_BITS
], 0, 0, 0);
573 CF_INLINE Boolean
__CFRunLoopObserverRepeats(CFRunLoopObserverRef rlo
) {
574 return (Boolean
)__CFBitfieldGetValue(((const CFRuntimeBase
*)rlo
)->_cfinfo
[CF_INFO_BITS
], 1, 1);
577 CF_INLINE
void __CFRunLoopObserverSetRepeats(CFRunLoopObserverRef rlo
) {
578 __CFBitfieldSetValue(((CFRuntimeBase
*)rlo
)->_cfinfo
[CF_INFO_BITS
], 1, 1, 1);
581 CF_INLINE
void __CFRunLoopObserverUnsetRepeats(CFRunLoopObserverRef rlo
) {
582 __CFBitfieldSetValue(((CFRuntimeBase
*)rlo
)->_cfinfo
[CF_INFO_BITS
], 1, 1, 0);
585 CF_INLINE
void __CFRunLoopObserverLock(CFRunLoopObserverRef rlo
) {
586 __CFSpinLock(&(rlo
->_lock
));
589 CF_INLINE
void __CFRunLoopObserverUnlock(CFRunLoopObserverRef rlo
) {
590 __CFSpinUnlock(&(rlo
->_lock
));
593 static void __CFRunLoopObserverSchedule(CFRunLoopObserverRef rlo
, CFRunLoopRef rl
, CFRunLoopModeRef rlm
) {
594 __CFRunLoopObserverLock(rlo
);
595 if (0 == rlo
->_rlCount
) {
599 __CFRunLoopObserverUnlock(rlo
);
602 static void __CFRunLoopObserverCancel(CFRunLoopObserverRef rlo
, CFRunLoopRef rl
, CFRunLoopModeRef rlm
) {
603 __CFRunLoopObserverLock(rlo
);
605 if (0 == rlo
->_rlCount
) {
606 rlo
->_runLoop
= NULL
;
608 __CFRunLoopObserverUnlock(rlo
);
611 struct __CFRunLoopTimer
{
614 CFRunLoopRef _runLoop
;
616 #if DEPLOYMENT_TARGET_MACOSX
617 mach_port_name_t _port
;
619 CFIndex _order
; /* immutable */
620 int64_t _fireTSR
; /* TSR units */
621 int64_t _intervalTSR
; /* immutable; 0 means non-repeating; TSR units */
622 CFRunLoopTimerCallBack _callout
; /* immutable */
623 CFRunLoopTimerContext _context
; /* immutable, except invalidation */
626 /* Bit 0 of the base reserved bits is used for firing state */
627 /* Bit 1 of the base reserved bits is used for fired-during-callout state */
629 CF_INLINE Boolean
__CFRunLoopTimerIsFiring(CFRunLoopTimerRef rlt
) {
630 return (Boolean
)__CFBitfieldGetValue(((const CFRuntimeBase
*)rlt
)->_cfinfo
[CF_INFO_BITS
], 0, 0);
633 CF_INLINE
void __CFRunLoopTimerSetFiring(CFRunLoopTimerRef rlt
) {
634 __CFBitfieldSetValue(((CFRuntimeBase
*)rlt
)->_cfinfo
[CF_INFO_BITS
], 0, 0, 1);
637 CF_INLINE
void __CFRunLoopTimerUnsetFiring(CFRunLoopTimerRef rlt
) {
638 __CFBitfieldSetValue(((CFRuntimeBase
*)rlt
)->_cfinfo
[CF_INFO_BITS
], 0, 0, 0);
641 CF_INLINE Boolean
__CFRunLoopTimerDidFire(CFRunLoopTimerRef rlt
) {
642 return (Boolean
)__CFBitfieldGetValue(((const CFRuntimeBase
*)rlt
)->_cfinfo
[CF_INFO_BITS
], 1, 1);
645 CF_INLINE
void __CFRunLoopTimerSetDidFire(CFRunLoopTimerRef rlt
) {
646 __CFBitfieldSetValue(((CFRuntimeBase
*)rlt
)->_cfinfo
[CF_INFO_BITS
], 1, 1, 1);
649 CF_INLINE
void __CFRunLoopTimerUnsetDidFire(CFRunLoopTimerRef rlt
) {
650 __CFBitfieldSetValue(((CFRuntimeBase
*)rlt
)->_cfinfo
[CF_INFO_BITS
], 1, 1, 0);
653 CF_INLINE
void __CFRunLoopTimerLock(CFRunLoopTimerRef rlt
) {
654 __CFSpinLock(&(rlt
->_lock
));
657 CF_INLINE
void __CFRunLoopTimerUnlock(CFRunLoopTimerRef rlt
) {
658 __CFSpinUnlock(&(rlt
->_lock
));
661 static CFSpinLock_t __CFRLTFireTSRLock
= CFSpinLockInit
;
663 CF_INLINE
void __CFRunLoopTimerFireTSRLock(void) {
664 __CFSpinLock(&__CFRLTFireTSRLock
);
667 CF_INLINE
void __CFRunLoopTimerFireTSRUnlock(void) {
668 __CFSpinUnlock(&__CFRLTFireTSRLock
);
671 #if DEPLOYMENT_TARGET_MACOSX
672 static CFMutableDictionaryRef __CFRLTPortMap
= NULL
;
673 static CFSpinLock_t __CFRLTPortMapLock
= CFSpinLockInit
;
675 CF_INLINE
void __CFRunLoopTimerPortMapLock(void) {
676 __CFSpinLock(&__CFRLTPortMapLock
);
679 CF_INLINE
void __CFRunLoopTimerPortMapUnlock(void) {
680 __CFSpinUnlock(&__CFRLTPortMapLock
);
684 static void __CFRunLoopTimerSchedule(CFRunLoopTimerRef rlt
, CFRunLoopRef rl
, CFRunLoopModeRef rlm
) {
685 #if DEPLOYMENT_TARGET_MACOSX
686 __CFRunLoopTimerLock(rlt
);
687 if (0 == rlt
->_rlCount
) {
689 if (MACH_PORT_NULL
== rlt
->_port
) {
690 rlt
->_port
= mk_timer_create();
692 __CFRunLoopTimerPortMapLock();
693 if (NULL
== __CFRLTPortMap
) {
694 __CFRLTPortMap
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, NULL
, NULL
);
696 CFDictionarySetValue(__CFRLTPortMap
, (void *)(uintptr_t)rlt
->_port
, rlt
);
697 __CFRunLoopTimerPortMapUnlock();
700 mach_port_insert_member(mach_task_self(), rlt
->_port
, rlm
->_portSet
);
701 mk_timer_arm(rlt
->_port
, __CFUInt64ToAbsoluteTime(rlt
->_fireTSR
));
702 __CFRunLoopTimerUnlock(rlt
);
706 static void __CFRunLoopTimerCancel(CFRunLoopTimerRef rlt
, CFRunLoopRef rl
, CFRunLoopModeRef rlm
) {
707 #if DEPLOYMENT_TARGET_MACOSX
708 __CFRunLoopTimerLock(rlt
);
709 __CFPortSetRemove(rlt
->_port
, rlm
->_portSet
);
711 if (0 == rlt
->_rlCount
) {
712 __CFRunLoopTimerPortMapLock();
713 if (NULL
!= __CFRLTPortMap
) {
714 CFDictionaryRemoveValue(__CFRLTPortMap
, (void *)(uintptr_t)rlt
->_port
);
716 __CFRunLoopTimerPortMapUnlock();
717 rlt
->_runLoop
= NULL
;
718 mk_timer_cancel(rlt
->_port
, NULL
);
720 __CFRunLoopTimerUnlock(rlt
);
724 // Caller must hold the Timer lock for safety
725 static void __CFRunLoopTimerRescheduleWithAllModes(CFRunLoopTimerRef rlt
, CFRunLoopRef rl
) {
726 #if DEPLOYMENT_TARGET_MACOSX
727 mk_timer_arm(rlt
->_port
, __CFUInt64ToAbsoluteTime(rlt
->_fireTSR
));
733 CONST_STRING_DECL(kCFRunLoopDefaultMode
, "kCFRunLoopDefaultMode")
734 CONST_STRING_DECL(kCFRunLoopCommonModes
, "kCFRunLoopCommonModes")
738 CFRunLoopSourceRef result
;
741 static void __CFRunLoopFindSource(const void *value
, void *ctx
) {
742 CFRunLoopSourceRef rls
= (CFRunLoopSourceRef
)value
;
743 struct _findsource
*context
= (struct _findsource
*)ctx
;
745 if (NULL
!= context
->result
) return;
746 if (1 != rls
->_context
.version0
.version
) return;
747 __CFRunLoopSourceLock(rls
);
748 port
= rls
->_context
.version1
.getPort(rls
->_context
.version1
.info
);
749 if (port
== context
->port
) {
750 context
->result
= rls
;
752 __CFRunLoopSourceUnlock(rls
);
755 // call with rl and rlm locked
756 static CFRunLoopSourceRef
__CFRunLoopModeFindSourceForMachPort(CFRunLoopRef rl
, CFRunLoopModeRef rlm
, __CFPort port
) { /* DOES CALLOUT */
758 struct _findsource context
= {port
, NULL
};
759 if (NULL
!= rlm
->_sources
) {
760 CFSetApplyFunction(rlm
->_sources
, (__CFRunLoopFindSource
), &context
);
762 if (NULL
== context
.result
&& NULL
!= rlm
->_submodes
) {
764 for (idx
= 0, cnt
= CFArrayGetCount(rlm
->_submodes
); idx
< cnt
; idx
++) {
765 CFRunLoopSourceRef source
= NULL
;
766 CFStringRef modeName
= (CFStringRef
)CFArrayGetValueAtIndex(rlm
->_submodes
, idx
);
767 CFRunLoopModeRef subrlm
;
768 subrlm
= __CFRunLoopFindMode(rl
, modeName
, false);
769 if (NULL
!= subrlm
) {
770 source
= __CFRunLoopModeFindSourceForMachPort(rl
, subrlm
, port
);
771 __CFRunLoopModeUnlock(subrlm
);
773 if (NULL
!= source
) {
774 context
.result
= source
;
779 return context
.result
;
782 #if DEPLOYMENT_TARGET_MACOSX
783 // call with rl and rlm locked
784 static CFRunLoopTimerRef
__CFRunLoopModeFindTimerForMachPort(CFRunLoopModeRef rlm
, __CFPort port
) {
786 CFRunLoopTimerRef result
= NULL
;
787 __CFRunLoopTimerPortMapLock();
788 if (NULL
!= __CFRLTPortMap
) {
789 result
= (CFRunLoopTimerRef
)CFDictionaryGetValue(__CFRLTPortMap
, (void *)(uintptr_t)port
);
791 __CFRunLoopTimerPortMapUnlock();
796 // Remove backreferences the mode's sources have to the rl (context);
797 // the primary purpose of rls->_runLoops is so that Invalidation can remove
798 // the source from the run loops it is in, but during deallocation of a
799 // run loop, we already know that the sources are going to be punted
800 // from it, so invalidation of sources does not need to remove from a
801 // deallocating run loop.
802 static void __CFRunLoopCleanseSources(const void *value
, void *context
) {
803 CFRunLoopModeRef rlm
= (CFRunLoopModeRef
)value
;
804 CFRunLoopRef rl
= (CFRunLoopRef
)context
;
806 const void **list
, *buffer
[256];
807 if (NULL
== rlm
->_sources
) return;
808 cnt
= CFSetGetCount(rlm
->_sources
);
809 list
= (cnt
<= 256) ? buffer
: CFAllocatorAllocate(kCFAllocatorSystemDefault
, cnt
* sizeof(void *), 0);
810 CFSetGetValues(rlm
->_sources
, list
);
811 for (idx
= 0; idx
< cnt
; idx
++) {
812 CFRunLoopSourceRef rls
= (CFRunLoopSourceRef
)list
[idx
];
813 __CFRunLoopSourceLock(rls
);
814 if (NULL
!= rls
->_runLoops
) {
815 CFBagRemoveValue(rls
->_runLoops
, rl
);
817 __CFRunLoopSourceUnlock(rls
);
819 if (list
!= buffer
) CFAllocatorDeallocate(kCFAllocatorSystemDefault
, list
);
822 static void __CFRunLoopDeallocateSources(const void *value
, void *context
) {
823 CFRunLoopModeRef rlm
= (CFRunLoopModeRef
)value
;
824 CFRunLoopRef rl
= (CFRunLoopRef
)context
;
826 const void **list
, *buffer
[256];
827 if (NULL
== rlm
->_sources
) return;
828 cnt
= CFSetGetCount(rlm
->_sources
);
829 list
= (cnt
<= 256) ? buffer
: CFAllocatorAllocate(kCFAllocatorSystemDefault
, cnt
* sizeof(void *), 0);
830 CFSetGetValues(rlm
->_sources
, list
);
831 for (idx
= 0; idx
< cnt
; idx
++) {
834 CFSetRemoveAllValues(rlm
->_sources
);
835 for (idx
= 0; idx
< cnt
; idx
++) {
836 __CFRunLoopSourceCancel((CFRunLoopSourceRef
)list
[idx
], rl
, rlm
);
837 CFRelease(list
[idx
]);
839 if (list
!= buffer
) CFAllocatorDeallocate(kCFAllocatorSystemDefault
, list
);
842 static void __CFRunLoopDeallocateObservers(const void *value
, void *context
) {
843 CFRunLoopModeRef rlm
= (CFRunLoopModeRef
)value
;
844 CFRunLoopRef rl
= (CFRunLoopRef
)context
;
846 const void **list
, *buffer
[256];
847 if (NULL
== rlm
->_observers
) return;
848 cnt
= CFSetGetCount(rlm
->_observers
);
849 list
= (cnt
<= 256) ? buffer
: CFAllocatorAllocate(kCFAllocatorSystemDefault
, cnt
* sizeof(void *), 0);
850 CFSetGetValues(rlm
->_observers
, list
);
851 for (idx
= 0; idx
< cnt
; idx
++) {
854 CFSetRemoveAllValues(rlm
->_observers
);
855 for (idx
= 0; idx
< cnt
; idx
++) {
856 __CFRunLoopObserverCancel((CFRunLoopObserverRef
)list
[idx
], rl
, rlm
);
857 CFRelease(list
[idx
]);
859 if (list
!= buffer
) CFAllocatorDeallocate(kCFAllocatorSystemDefault
, list
);
862 static void __CFRunLoopDeallocateTimers(const void *value
, void *context
) {
863 CFRunLoopModeRef rlm
= (CFRunLoopModeRef
)value
;
864 CFRunLoopRef rl
= (CFRunLoopRef
)context
;
866 const void **list
, *buffer
[256];
867 if (NULL
== rlm
->_timers
) return;
868 cnt
= CFSetGetCount(rlm
->_timers
);
869 list
= (cnt
<= 256) ? buffer
: CFAllocatorAllocate(kCFAllocatorSystemDefault
, cnt
* sizeof(void *), 0);
870 CFSetGetValues(rlm
->_timers
, list
);
871 for (idx
= 0; idx
< cnt
; idx
++) {
874 CFSetRemoveAllValues(rlm
->_timers
);
875 for (idx
= 0; idx
< cnt
; idx
++) {
876 __CFRunLoopTimerCancel((CFRunLoopTimerRef
)list
[idx
], rl
, rlm
);
877 CFRelease(list
[idx
]);
879 if (list
!= buffer
) CFAllocatorDeallocate(kCFAllocatorSystemDefault
, list
);
882 static void __CFRunLoopDeallocate(CFTypeRef cf
) {
883 CFRunLoopRef rl
= (CFRunLoopRef
)cf
;
884 /* We try to keep the run loop in a valid state as long as possible,
885 since sources may have non-retained references to the run loop.
886 Another reason is that we don't want to lock the run loop for
887 callback reasons, if we can get away without that. We start by
888 eliminating the sources, since they are the most likely to call
889 back into the run loop during their "cancellation". Common mode
890 items will be removed from the mode indirectly by the following
892 __CFRunLoopSetDeallocating(rl
);
893 if (NULL
!= rl
->_modes
) {
894 CFSetApplyFunction(rl
->_modes
, (__CFRunLoopCleanseSources
), rl
); // remove references to rl
895 CFSetApplyFunction(rl
->_modes
, (__CFRunLoopDeallocateSources
), rl
);
896 CFSetApplyFunction(rl
->_modes
, (__CFRunLoopDeallocateObservers
), rl
);
897 CFSetApplyFunction(rl
->_modes
, (__CFRunLoopDeallocateTimers
), rl
);
900 if (NULL
!= rl
->_commonModeItems
) {
901 CFRelease(rl
->_commonModeItems
);
903 if (NULL
!= rl
->_commonModes
) {
904 CFRelease(rl
->_commonModes
);
906 if (NULL
!= rl
->_modes
) {
907 CFRelease(rl
->_modes
);
909 __CFPortFree(rl
->_wakeUpPort
);
910 rl
->_wakeUpPort
= CFPORT_NULL
;
911 __CFRunLoopUnlock(rl
);
914 static const CFRuntimeClass __CFRunLoopModeClass
= {
919 __CFRunLoopModeDeallocate
,
920 __CFRunLoopModeEqual
,
923 __CFRunLoopModeCopyDescription
926 static const CFRuntimeClass __CFRunLoopClass
= {
931 __CFRunLoopDeallocate
,
935 __CFRunLoopCopyDescription
938 __private_extern__
void __CFRunLoopInitialize(void) {
939 __kCFRunLoopTypeID
= _CFRuntimeRegisterClass(&__CFRunLoopClass
);
940 __kCFRunLoopModeTypeID
= _CFRuntimeRegisterClass(&__CFRunLoopModeClass
);
943 CFTypeID
CFRunLoopGetTypeID(void) {
944 return __kCFRunLoopTypeID
;
947 static CFRunLoopRef
__CFRunLoopCreate(void) {
948 CFRunLoopRef loop
= NULL
;
949 CFRunLoopModeRef rlm
;
950 uint32_t size
= sizeof(struct __CFRunLoop
) - sizeof(CFRuntimeBase
);
951 loop
= (CFRunLoopRef
)_CFRuntimeCreateInstance(kCFAllocatorSystemDefault
, __kCFRunLoopTypeID
, size
, NULL
);
955 loop
->_stopped
= NULL
;
956 CF_SPINLOCK_INIT_FOR_STRUCTS(loop
->_lock
);
957 loop
->_wakeUpPort
= __CFPortAllocate();
958 if (CFPORT_NULL
== loop
->_wakeUpPort
) HALT
;
959 loop
->_commonModes
= CFSetCreateMutable(CFGetAllocator(loop
), 0, &kCFTypeSetCallBacks
);
960 CFSetAddValue(loop
->_commonModes
, kCFRunLoopDefaultMode
);
961 loop
->_commonModeItems
= NULL
;
962 loop
->_currentMode
= NULL
;
963 loop
->_modes
= CFSetCreateMutable(CFGetAllocator(loop
), 0, &kCFTypeSetCallBacks
);
964 _CFSetSetCapacity(loop
->_modes
, 10);
965 loop
->_counterpart
= NULL
;
966 rlm
= __CFRunLoopFindMode(loop
, kCFRunLoopDefaultMode
, true);
967 if (NULL
!= rlm
) __CFRunLoopModeUnlock(rlm
);
971 static void __CFRunLoopRemoveAllSources(CFRunLoopRef rl
, CFStringRef modeName
);
973 static CFMutableDictionaryRef __CFRunLoops
= NULL
;
974 static char setMainLoop
= 0;
975 static CFSpinLock_t loopsLock
= CFSpinLockInit
;
977 // If this is called on a non-main thread, and the main thread pthread_t is passed in,
978 // and this has not yet beed called on the main thread (since the last fork(), this will
979 // produce a different run loop that will probably be tossed away eventually, than the
980 // main thread run loop. There's nothing much we can do about that, without a call to
981 // fetch the main thread's pthread_t from the pthreads subsystem.
983 // t==0 is a synonym for "main thread" that always works
984 static CFRunLoopRef
_CFRunLoop0(pthread_t t
) {
986 __CFSpinLock(&loopsLock
);
988 __CFSpinUnlock(&loopsLock
);
989 CFMutableDictionaryRef dict
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, NULL
, &kCFTypeDictionaryValueCallBacks
);
990 CFRunLoopRef mainLoop
= __CFRunLoopCreate();
991 CFDictionarySetValue(dict
, pthreadPointer(kNilPthreadT
), mainLoop
);
992 if (!OSAtomicCompareAndSwapPtrBarrier(NULL
, dict
, (void * volatile *)&__CFRunLoops
)) {
996 __CFSpinLock(&loopsLock
);
998 if (pthread_main_np() && pthread_equal(t
, pthread_self())) {
1001 loop
= (CFRunLoopRef
)CFDictionaryGetValue(__CFRunLoops
, pthreadPointer(t
));
1003 __CFSpinUnlock(&loopsLock
);
1004 CFRunLoopRef newLoop
= __CFRunLoopCreate();
1005 __CFSpinLock(&loopsLock
);
1006 loop
= (CFRunLoopRef
)CFDictionaryGetValue(__CFRunLoops
, pthreadPointer(t
));
1008 CFDictionarySetValue(__CFRunLoops
, pthreadPointer(t
), newLoop
);
1013 if (!setMainLoop
&& pthread_main_np()) {
1014 if (pthread_equal(t
, kNilPthreadT
)) {
1015 CFDictionarySetValue(__CFRunLoops
, pthreadPointer(pthread_self()), loop
);
1017 CFRunLoopRef mainLoop
= (CFRunLoopRef
)CFDictionaryGetValue(__CFRunLoops
, pthreadPointer(kNilPthreadT
));
1018 CFDictionarySetValue(__CFRunLoops
, pthreadPointer(pthread_self()), mainLoop
);
1022 __CFSpinUnlock(&loopsLock
);
1026 // Called for each thread as it exits
1027 static void __CFFinalizeRunLoop(void *arg
) {
1028 CFRunLoopRef rl
= NULL
;
1029 __CFSpinLock(&loopsLock
);
1031 rl
= (CFRunLoopRef
)CFDictionaryGetValue(__CFRunLoops
, pthreadPointer(pthread_self()));
1032 if (rl
) CFRetain(rl
);
1033 CFDictionaryRemoveValue(__CFRunLoops
, pthreadPointer(pthread_self()));
1035 __CFSpinUnlock(&loopsLock
);
1036 if (rl
&& CFRunLoopGetMain() != rl
) {
1037 // purge all sources before deallocation
1038 CFArrayRef array
= CFRunLoopCopyAllModes(rl
);
1039 for (CFIndex idx
= CFArrayGetCount(array
); idx
--;) {
1040 CFStringRef modeName
= CFArrayGetValueAtIndex(array
, idx
);
1041 __CFRunLoopRemoveAllSources(rl
, modeName
);
1043 __CFRunLoopRemoveAllSources(rl
, kCFRunLoopCommonModes
);
1051 __private_extern__
void _CFRunLoop1(void) { __CFFinalizeRunLoop(0); }
1053 void _CFRunLoopSetCurrent(CFRunLoopRef rl
) {
1054 CFRunLoopRef currentLoop
= CFRunLoopGetCurrent();
1055 if (rl
!= currentLoop
) {
1056 __CFSpinLock(&loopsLock
);
1058 CFDictionarySetValue(__CFRunLoops
, pthreadPointer(pthread_self()), rl
);
1060 CFDictionaryRemoveValue(__CFRunLoops
, pthreadPointer(pthread_self()));
1062 __CFSpinUnlock(&loopsLock
);
1066 CFRunLoopRef
CFRunLoopGetMain(void) {
1068 return _CFRunLoop0(kNilPthreadT
);
1071 CFRunLoopRef
CFRunLoopGetCurrent(void) {
1073 return _CFRunLoop0(pthread_self());
1076 CFStringRef
CFRunLoopCopyCurrentMode(CFRunLoopRef rl
) {
1078 CFStringRef result
= NULL
;
1079 __CFRunLoopLock(rl
);
1080 if (NULL
!= rl
->_currentMode
) {
1081 result
= CFRetain(rl
->_currentMode
->_name
);
1083 __CFRunLoopUnlock(rl
);
1087 static void __CFRunLoopGetModeName(const void *value
, void *context
) {
1088 CFRunLoopModeRef rlm
= (CFRunLoopModeRef
)value
;
1089 CFMutableArrayRef array
= (CFMutableArrayRef
)context
;
1090 CFArrayAppendValue(array
, rlm
->_name
);
1093 CFArrayRef
CFRunLoopCopyAllModes(CFRunLoopRef rl
) {
1095 CFMutableArrayRef array
;
1096 __CFRunLoopLock(rl
);
1097 array
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, CFSetGetCount(rl
->_modes
), &kCFTypeArrayCallBacks
);
1098 CFSetApplyFunction(rl
->_modes
, (__CFRunLoopGetModeName
), array
);
1099 __CFRunLoopUnlock(rl
);
1103 static void __CFRunLoopAddItemsToCommonMode(const void *value
, void *ctx
) {
1104 CFTypeRef item
= (CFTypeRef
)value
;
1105 CFRunLoopRef rl
= (CFRunLoopRef
)(((CFTypeRef
*)ctx
)[0]);
1106 CFStringRef modeName
= (CFStringRef
)(((CFTypeRef
*)ctx
)[1]);
1107 if (CFGetTypeID(item
) == __kCFRunLoopSourceTypeID
) {
1108 CFRunLoopAddSource(rl
, (CFRunLoopSourceRef
)item
, modeName
);
1109 } else if (CFGetTypeID(item
) == __kCFRunLoopObserverTypeID
) {
1110 CFRunLoopAddObserver(rl
, (CFRunLoopObserverRef
)item
, modeName
);
1111 } else if (CFGetTypeID(item
) == __kCFRunLoopTimerTypeID
) {
1112 CFRunLoopAddTimer(rl
, (CFRunLoopTimerRef
)item
, modeName
);
1116 static void __CFRunLoopAddItemToCommonModes(const void *value
, void *ctx
) {
1117 CFStringRef modeName
= (CFStringRef
)value
;
1118 CFRunLoopRef rl
= (CFRunLoopRef
)(((CFTypeRef
*)ctx
)[0]);
1119 CFTypeRef item
= (CFTypeRef
)(((CFTypeRef
*)ctx
)[1]);
1120 if (CFGetTypeID(item
) == __kCFRunLoopSourceTypeID
) {
1121 CFRunLoopAddSource(rl
, (CFRunLoopSourceRef
)item
, modeName
);
1122 } else if (CFGetTypeID(item
) == __kCFRunLoopObserverTypeID
) {
1123 CFRunLoopAddObserver(rl
, (CFRunLoopObserverRef
)item
, modeName
);
1124 } else if (CFGetTypeID(item
) == __kCFRunLoopTimerTypeID
) {
1125 CFRunLoopAddTimer(rl
, (CFRunLoopTimerRef
)item
, modeName
);
1129 static void __CFRunLoopRemoveItemFromCommonModes(const void *value
, void *ctx
) {
1130 CFStringRef modeName
= (CFStringRef
)value
;
1131 CFRunLoopRef rl
= (CFRunLoopRef
)(((CFTypeRef
*)ctx
)[0]);
1132 CFTypeRef item
= (CFTypeRef
)(((CFTypeRef
*)ctx
)[1]);
1133 if (CFGetTypeID(item
) == __kCFRunLoopSourceTypeID
) {
1134 CFRunLoopRemoveSource(rl
, (CFRunLoopSourceRef
)item
, modeName
);
1135 } else if (CFGetTypeID(item
) == __kCFRunLoopObserverTypeID
) {
1136 CFRunLoopRemoveObserver(rl
, (CFRunLoopObserverRef
)item
, modeName
);
1137 } else if (CFGetTypeID(item
) == __kCFRunLoopTimerTypeID
) {
1138 CFRunLoopRemoveTimer(rl
, (CFRunLoopTimerRef
)item
, modeName
);
1142 Boolean
_CFRunLoop01(CFRunLoopRef rl
, CFStringRef modeName
) {
1143 __CFRunLoopLock(rl
);
1144 Boolean present
= CFSetContainsValue(rl
->_commonModes
, modeName
);
1145 __CFRunLoopUnlock(rl
);
1149 void *_CFRunLoop02(CFRunLoopRef rl
) {
1150 return rl
->_counterpart
;
1153 void _CFRunLoop03(CFRunLoopRef rl
, void *ns
) {
1154 rl
->_counterpart
= ns
;
1157 void CFRunLoopAddCommonMode(CFRunLoopRef rl
, CFStringRef modeName
) {
1159 if (__CFRunLoopIsDeallocating(rl
)) return;
1160 __CFRunLoopLock(rl
);
1161 if (!CFSetContainsValue(rl
->_commonModes
, modeName
)) {
1162 CFSetRef set
= rl
->_commonModeItems
? CFSetCreateCopy(kCFAllocatorSystemDefault
, rl
->_commonModeItems
) : NULL
;
1163 CFSetAddValue(rl
->_commonModes
, modeName
);
1164 __CFRunLoopUnlock(rl
);
1166 CFTypeRef context
[2] = {rl
, modeName
};
1167 /* add all common-modes items to new mode */
1168 CFSetApplyFunction(set
, (__CFRunLoopAddItemsToCommonMode
), (void *)context
);
1172 __CFRunLoopUnlock(rl
);
1176 static CFComparisonResult
__CFRunLoopObserverQSortComparator(const void *val1
, const void *val2
, void *context
) {
1177 CFRunLoopObserverRef o1
= *((CFRunLoopObserverRef
*)val1
);
1178 CFRunLoopObserverRef o2
= *((CFRunLoopObserverRef
*)val2
);
1180 return (!o2
) ? kCFCompareEqualTo
: kCFCompareLessThan
;
1183 return kCFCompareGreaterThan
;
1185 if (o1
->_order
< o2
->_order
) return kCFCompareLessThan
;
1186 if (o2
->_order
< o1
->_order
) return kCFCompareGreaterThan
;
1187 return kCFCompareEqualTo
;
1191 /* rl is unlocked, rlm is locked on entrance and exit */
1192 /* ALERT: this should collect all the candidate observers from the top level
1193 * and all submodes, recursively, THEN start calling them, in order to obey
1194 * the ordering parameter. */
1195 static void __CFRunLoopDoObservers(CFRunLoopRef rl
, CFRunLoopModeRef rlm
, CFRunLoopActivity activity
) { /* DOES CALLOUT */
1198 CFArrayRef submodes
;
1200 /* Fire the observers */
1201 submodes
= (NULL
!= rlm
->_submodes
&& 0 < CFArrayGetCount(rlm
->_submodes
)) ? CFArrayCreateCopy(kCFAllocatorSystemDefault
, rlm
->_submodes
) : NULL
;
1202 if (NULL
!= rlm
->_observers
) {
1203 cnt
= CFSetGetCount(rlm
->_observers
);
1205 CFRunLoopObserverRef buffer
[(cnt
<= 1024) ? cnt
: 1];
1206 CFRunLoopObserverRef
*collectedObservers
= (cnt
<= 1024) ? buffer
: CFAllocatorAllocate(kCFAllocatorSystemDefault
, cnt
* sizeof(CFRunLoopObserverRef
), 0);
1207 CFSetGetValues(rlm
->_observers
, (const void **)collectedObservers
);
1208 for (idx
= 0; idx
< cnt
; idx
++) {
1209 CFRunLoopObserverRef rlo
= collectedObservers
[idx
];
1210 if (0 != (rlo
->_activities
& activity
) && __CFIsValid(rlo
) && !__CFRunLoopObserverIsFiring(rlo
)) {
1213 /* We're not interested in this one - set it to NULL so we don't process it later */
1214 collectedObservers
[idx
] = NULL
;
1217 __CFRunLoopModeUnlock(rlm
);
1218 CFQSortArray(collectedObservers
, cnt
, sizeof(CFRunLoopObserverRef
), __CFRunLoopObserverQSortComparator
, NULL
);
1219 for (idx
= 0; idx
< cnt
; idx
++) {
1220 CFRunLoopObserverRef rlo
= collectedObservers
[idx
];
1222 __CFRunLoopObserverLock(rlo
);
1223 if (__CFIsValid(rlo
)) {
1224 __CFRunLoopObserverUnlock(rlo
);
1225 __CFRunLoopObserverSetFiring(rlo
);
1226 rlo
->_callout(rlo
, activity
, rlo
->_context
.info
); /* CALLOUT */
1227 __CFRunLoopObserverUnsetFiring(rlo
);
1228 if (!__CFRunLoopObserverRepeats(rlo
)) {
1229 CFRunLoopObserverInvalidate(rlo
);
1232 __CFRunLoopObserverUnlock(rlo
);
1237 __CFRunLoopModeLock(rlm
);
1238 if (collectedObservers
!= buffer
) CFAllocatorDeallocate(kCFAllocatorSystemDefault
, collectedObservers
);
1241 if (NULL
!= submodes
) {
1242 __CFRunLoopModeUnlock(rlm
);
1243 for (idx
= 0, cnt
= CFArrayGetCount(submodes
); idx
< cnt
; idx
++) {
1244 CFStringRef modeName
= (CFStringRef
)CFArrayGetValueAtIndex(submodes
, idx
);
1245 CFRunLoopModeRef subrlm
;
1246 __CFRunLoopLock(rl
);
1247 subrlm
= __CFRunLoopFindMode(rl
, modeName
, false);
1248 __CFRunLoopUnlock(rl
);
1249 if (NULL
!= subrlm
) {
1250 __CFRunLoopDoObservers(rl
, subrlm
, activity
);
1251 __CFRunLoopModeUnlock(subrlm
);
1254 CFRelease(submodes
);
1255 __CFRunLoopModeLock(rlm
);
1259 static CFComparisonResult
__CFRunLoopSourceComparator(const void *val1
, const void *val2
, void *context
) {
1260 CFRunLoopSourceRef o1
= (CFRunLoopSourceRef
)val1
;
1261 CFRunLoopSourceRef o2
= (CFRunLoopSourceRef
)val2
;
1262 if (o1
->_order
< o2
->_order
) return kCFCompareLessThan
;
1263 if (o2
->_order
< o1
->_order
) return kCFCompareGreaterThan
;
1264 return kCFCompareEqualTo
;
1267 static void __CFRunLoopCollectSources0(const void *value
, void *context
) {
1268 CFRunLoopSourceRef rls
= (CFRunLoopSourceRef
)value
;
1269 CFTypeRef
*sources
= (CFTypeRef
*)context
;
1270 if (0 == rls
->_context
.version0
.version
&& __CFIsValid(rls
) && __CFRunLoopSourceIsSignaled(rls
)) {
1271 if (NULL
== *sources
) {
1272 *sources
= CFRetain(rls
);
1273 } else if (CFGetTypeID(*sources
) == __kCFRunLoopSourceTypeID
) {
1274 CFTypeRef oldrls
= *sources
;
1275 *sources
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeArrayCallBacks
);
1276 CFArrayAppendValue((CFMutableArrayRef
)*sources
, oldrls
);
1277 CFArrayAppendValue((CFMutableArrayRef
)*sources
, rls
);
1280 CFArrayAppendValue((CFMutableArrayRef
)*sources
, rls
);
1285 /* rl is unlocked, rlm is locked on entrance and exit */
1286 static Boolean
__CFRunLoopDoSources0(CFRunLoopRef rl
, CFRunLoopModeRef rlm
, Boolean stopAfterHandle
) { /* DOES CALLOUT */
1288 CFTypeRef sources
= NULL
;
1289 Boolean sourceHandled
= false;
1292 __CFRunLoopModeUnlock(rlm
); // locks have to be taken in order
1293 __CFRunLoopLock(rl
);
1294 __CFRunLoopModeLock(rlm
);
1295 /* Fire the version 0 sources */
1296 if (NULL
!= rlm
->_sources
&& 0 < CFSetGetCount(rlm
->_sources
)) {
1297 CFSetApplyFunction(rlm
->_sources
, (__CFRunLoopCollectSources0
), &sources
);
1299 for (idx
= 0, cnt
= (NULL
!= rlm
->_submodes
) ? CFArrayGetCount(rlm
->_submodes
) : 0; idx
< cnt
; idx
++) {
1300 CFStringRef modeName
= (CFStringRef
)CFArrayGetValueAtIndex(rlm
->_submodes
, idx
);
1301 CFRunLoopModeRef subrlm
;
1302 subrlm
= __CFRunLoopFindMode(rl
, modeName
, false);
1303 if (NULL
!= subrlm
) {
1304 if (NULL
!= subrlm
->_sources
&& 0 < CFSetGetCount(subrlm
->_sources
)) {
1305 CFSetApplyFunction(subrlm
->_sources
, (__CFRunLoopCollectSources0
), &sources
);
1307 __CFRunLoopModeUnlock(subrlm
);
1310 __CFRunLoopUnlock(rl
);
1311 if (NULL
!= sources
) {
1312 // sources is either a single (retained) CFRunLoopSourceRef or an array of (retained) CFRunLoopSourceRef
1313 __CFRunLoopModeUnlock(rlm
);
1314 if (CFGetTypeID(sources
) == __kCFRunLoopSourceTypeID
) {
1315 CFRunLoopSourceRef rls
= (CFRunLoopSourceRef
)sources
;
1316 __CFRunLoopSourceLock(rls
);
1317 __CFRunLoopSourceUnsetSignaled(rls
);
1318 if (__CFIsValid(rls
)) {
1319 __CFRunLoopSourceUnlock(rls
);
1320 if (NULL
!= rls
->_context
.version0
.perform
) {
1321 rls
->_context
.version0
.perform(rls
->_context
.version0
.info
); /* CALLOUT */
1324 sourceHandled
= true;
1326 __CFRunLoopSourceUnlock(rls
);
1329 cnt
= CFArrayGetCount(sources
);
1330 CFArraySortValues((CFMutableArrayRef
)sources
, CFRangeMake(0, cnt
), (__CFRunLoopSourceComparator
), NULL
);
1331 for (idx
= 0; idx
< cnt
; idx
++) {
1332 CFRunLoopSourceRef rls
= (CFRunLoopSourceRef
)CFArrayGetValueAtIndex(sources
, idx
);
1333 __CFRunLoopSourceLock(rls
);
1334 __CFRunLoopSourceUnsetSignaled(rls
);
1335 if (__CFIsValid(rls
)) {
1336 __CFRunLoopSourceUnlock(rls
);
1337 if (NULL
!= rls
->_context
.version0
.perform
) {
1338 rls
->_context
.version0
.perform(rls
->_context
.version0
.info
); /* CALLOUT */
1341 sourceHandled
= true;
1343 __CFRunLoopSourceUnlock(rls
);
1345 if (stopAfterHandle
&& sourceHandled
) {
1351 __CFRunLoopModeLock(rlm
);
1353 return sourceHandled
;
1356 // msg, size and reply are unused on Windows
1357 static Boolean
__CFRunLoopDoSource1(CFRunLoopRef rl
, CFRunLoopModeRef rlm
, CFRunLoopSourceRef rls
1358 #if DEPLOYMENT_TARGET_MACOSX
1359 , mach_msg_header_t
*msg
, CFIndex size
, mach_msg_header_t
**reply
1361 ) { /* DOES CALLOUT */
1363 Boolean sourceHandled
= false;
1365 /* Fire a version 1 source */
1367 __CFRunLoopModeUnlock(rlm
);
1368 __CFRunLoopSourceLock(rls
);
1369 if (__CFIsValid(rls
)) {
1370 __CFRunLoopSourceUnsetSignaled(rls
);
1371 __CFRunLoopSourceUnlock(rls
);
1372 if (NULL
!= rls
->_context
.version1
.perform
) {
1373 #if DEPLOYMENT_TARGET_MACOSX
1374 *reply
= rls
->_context
.version1
.perform(msg
, size
, kCFAllocatorSystemDefault
, rls
->_context
.version1
.info
); /* CALLOUT */
1377 if (_LogCFRunLoop
) { CFLog(kCFLogLevelDebug
, CFSTR("%p (%s) __CFRunLoopDoSource1 performing rls %p"), CFRunLoopGetCurrent(), *_CFGetProgname(), rls
); }
1378 rls
->_context
.version1
.perform(rls
->_context
.version1
.info
); /* CALLOUT */
1382 if (_LogCFRunLoop
) { CFLog(kCFLogLevelDebug
, CFSTR("%p (%s) __CFRunLoopDoSource1 perform is NULL"), CFRunLoopGetCurrent(), *_CFGetProgname()); }
1384 sourceHandled
= true;
1386 if (_LogCFRunLoop
) { CFLog(kCFLogLevelDebug
, CFSTR("%p (%s) __CFRunLoopDoSource1 rls %p is invalid"), CFRunLoopGetCurrent(), *_CFGetProgname(), rls
); }
1387 __CFRunLoopSourceUnlock(rls
);
1390 __CFRunLoopModeLock(rlm
);
1391 return sourceHandled
;
1394 static Boolean
__CFRunLoopDoTimer(CFRunLoopRef rl
, CFRunLoopModeRef rlm
, CFRunLoopTimerRef rlt
) { /* DOES CALLOUT */
1395 Boolean timerHandled
= false;
1396 int64_t oldFireTSR
= 0;
1400 __CFRunLoopModeUnlock(rlm
);
1401 __CFRunLoopTimerLock(rlt
);
1402 if (__CFIsValid(rlt
) && !__CFRunLoopTimerIsFiring(rlt
)) {
1403 __CFRunLoopTimerUnsetDidFire(rlt
);
1404 __CFRunLoopTimerSetFiring(rlt
);
1405 __CFRunLoopTimerUnlock(rlt
);
1406 __CFRunLoopTimerFireTSRLock();
1407 oldFireTSR
= rlt
->_fireTSR
;
1408 __CFRunLoopTimerFireTSRUnlock();
1409 rlt
->_callout(rlt
, rlt
->_context
.info
); /* CALLOUT */
1411 __CFRunLoopTimerUnsetFiring(rlt
);
1412 timerHandled
= true;
1414 // If the timer fires while it is firing in a higher activiation,
1415 // it is not allowed to fire, but we have to remember that fact.
1416 // Later, if the timer's fire date is being handled manually, we
1417 // need to re-arm the kernel timer, since it has possibly already
1418 // fired (this firing which is being skipped, say) and the timer
1419 // will permanently stop if we completely drop this firing.
1420 if (__CFRunLoopTimerIsFiring(rlt
)) __CFRunLoopTimerSetDidFire(rlt
);
1421 __CFRunLoopTimerUnlock(rlt
);
1423 if (__CFIsValid(rlt
) && timerHandled
) {
1424 if (0 == rlt
->_intervalTSR
) {
1425 CFRunLoopTimerInvalidate(rlt
); /* DOES CALLOUT */
1427 /* This is just a little bit tricky: we want to support calling
1428 * CFRunLoopTimerSetNextFireDate() from within the callout and
1429 * honor that new time here if it is a later date, otherwise
1430 * it is completely ignored. */
1431 int64_t currentFireTSR
;
1432 __CFRunLoopTimerFireTSRLock();
1433 currentFireTSR
= rlt
->_fireTSR
;
1434 if (oldFireTSR
< currentFireTSR
) {
1435 /* Next fire TSR was set, and set to a date after the previous
1436 * fire date, so we honor it. */
1437 if (__CFRunLoopTimerDidFire(rlt
)) {
1438 __CFRunLoopTimerRescheduleWithAllModes(rlt
, rl
);
1439 __CFRunLoopTimerUnsetDidFire(rlt
);
1442 if ((uint64_t)LLONG_MAX
<= (uint64_t)oldFireTSR
+ (uint64_t)rlt
->_intervalTSR
) {
1443 currentFireTSR
= LLONG_MAX
;
1445 int64_t currentTSR
= (int64_t)__CFReadTSR();
1446 currentFireTSR
= oldFireTSR
;
1447 while (currentFireTSR
<= currentTSR
) {
1448 currentFireTSR
+= rlt
->_intervalTSR
;
1451 rlt
->_fireTSR
= currentFireTSR
;
1452 __CFRunLoopTimerRescheduleWithAllModes(rlt
, rl
);
1454 __CFRunLoopTimerFireTSRUnlock();
1458 __CFRunLoopModeLock(rlm
);
1459 return timerHandled
;
1462 CF_EXPORT Boolean
_CFRunLoopFinished(CFRunLoopRef rl
, CFStringRef modeName
) {
1464 CFRunLoopModeRef rlm
;
1465 Boolean result
= false;
1466 __CFRunLoopLock(rl
);
1467 rlm
= __CFRunLoopFindMode(rl
, modeName
, false);
1468 if (NULL
== rlm
|| __CFRunLoopModeIsEmpty(rl
, rlm
)) {
1471 __CFRunLoopUnlock(rl
);
1472 if (rlm
) __CFRunLoopModeUnlock(rlm
);
1476 // rl is locked, rlm is locked on entry and exit
1477 static void __CFRunLoopModeAddPortsToPortSet(CFRunLoopRef rl
, CFRunLoopModeRef rlm
, __CFPortSet portSet
) {
1479 const void **list
, *buffer
[256];
1481 // Timers and version 1 sources go into the portSet currently
1482 if (NULL
!= rlm
->_sources
) {
1483 cnt
= CFSetGetCount(rlm
->_sources
);
1484 list
= (cnt
<= 256) ? buffer
: CFAllocatorAllocate(kCFAllocatorSystemDefault
, cnt
* sizeof(void *), 0);
1485 CFSetGetValues(rlm
->_sources
, list
);
1486 for (idx
= 0; idx
< cnt
; idx
++) {
1487 CFRunLoopSourceRef rls
= (CFRunLoopSourceRef
)list
[idx
];
1488 if (1 == rls
->_context
.version0
.version
) {
1489 __CFPort port
= rls
->_context
.version1
.getPort(rls
->_context
.version1
.info
); /* CALLOUT */
1490 if (CFPORT_NULL
!= port
) {
1491 __CFPortSetInsert(port
, portSet
);
1495 if (list
!= buffer
) CFAllocatorDeallocate(kCFAllocatorSystemDefault
, list
);
1497 #if DEPLOYMENT_TARGET_MACOSX
1498 if (NULL
!= rlm
->_timers
) {
1499 cnt
= CFSetGetCount(rlm
->_timers
);
1500 list
= (cnt
<= 256) ? buffer
: CFAllocatorAllocate(kCFAllocatorSystemDefault
, cnt
* sizeof(void *), 0);
1501 CFSetGetValues(rlm
->_timers
, list
);
1502 for (idx
= 0; idx
< cnt
; idx
++) {
1503 CFRunLoopTimerRef rlt
= (CFRunLoopTimerRef
)list
[idx
];
1504 if (MACH_PORT_NULL
!= rlt
->_port
) {
1505 mach_port_insert_member(mach_task_self(), rlt
->_port
, portSet
);
1508 if (list
!= buffer
) CFAllocatorDeallocate(kCFAllocatorSystemDefault
, list
);
1511 // iterate over submodes
1512 for (idx
= 0, cnt
= NULL
!= rlm
->_submodes
? CFArrayGetCount(rlm
->_submodes
) : 0; idx
< cnt
; idx
++) {
1513 CFStringRef modeName
= (CFStringRef
)CFArrayGetValueAtIndex(rlm
->_submodes
, idx
);
1514 CFRunLoopModeRef subrlm
;
1515 subrlm
= __CFRunLoopFindMode(rl
, modeName
, false);
1516 if (NULL
!= subrlm
) {
1517 __CFRunLoopModeAddPortsToPortSet(rl
, subrlm
, portSet
);
1518 __CFRunLoopModeUnlock(subrlm
);
1523 static __CFPortSet _LastMainWaitSet
= 0;
1525 // return NO if we're the main runloop and there are no messages waiting on the port set
1526 int _CFRunLoopInputsReady(void) {
1528 // XXX_PCB: the following 2 lines aren't safe to call during GC, because another
1529 // thread may have entered CFRunLoopGetMain(), which grabs a spink lock, and then
1530 // is suspended by the GC. We can check for the main thread more directly
1531 // by calling pthread_main_np().
1532 // CFRunLoopRef current = CFRunLoopGetMain()
1533 // if (current != CFRunLoopGetMain()) return true;
1534 #if DEPLOYMENT_TARGET_MACOSX
1535 if (!pthread_main_np()) return true;
1537 // XXX_PCB: can't be any messages waiting if the wait set is NULL.
1538 if (_LastMainWaitSet
== MACH_PORT_NULL
) return false;
1540 // prepare a message header with no space for any data, nor a trailer
1541 mach_msg_header_t msg
;
1542 msg
.msgh_size
= sizeof(msg
); // just the header, ma'am
1543 // need the waitset, actually XXX
1544 msg
.msgh_local_port
= _LastMainWaitSet
;
1545 msg
.msgh_remote_port
= MACH_PORT_NULL
;
1548 kern_return_t ret
= mach_msg(&msg
, MACH_RCV_MSG
| MACH_RCV_TIMEOUT
| MACH_RCV_LARGE
, 0, msg
.msgh_size
, _LastMainWaitSet
, 0, MACH_PORT_NULL
);
1550 return (MACH_RCV_TOO_LARGE
== ret
);
1556 static void print_msg_scan_header(void) {
1557 printf("======== ======== ======== ========\n");
1558 printf("description\tport\tport type\t\treferences\n");
1561 static void print_one_port_info(const char *desc
, mach_port_t port
, mach_msg_type_name_t type
) {
1562 mach_port_urefs_t refs
;
1563 kern_return_t ret
= mach_port_get_refs(mach_task_self(), port
, MACH_PORT_RIGHT_SEND
, &refs
);
1564 if (ret
!= KERN_SUCCESS
) refs
= 0;
1565 const char *type_name
= "???";
1567 case MACH_MSG_TYPE_MOVE_SEND
: type_name
= "MACH_MSG_TYPE_MOVE_SEND"; break;
1568 case MACH_MSG_TYPE_MOVE_SEND_ONCE
: type_name
= "MACH_MSG_TYPE_MOVE_SEND_ONCE"; break;
1569 case MACH_MSG_TYPE_MOVE_RECEIVE
: type_name
= "MACH_MSG_TYPE_MOVE_RECEIVE"; break;
1570 case MACH_MSG_TYPE_MAKE_SEND
: type_name
= "MACH_MSG_TYPE_MAKE_SEND"; break;
1571 case MACH_MSG_TYPE_MAKE_SEND_ONCE
: type_name
= "MACH_MSG_TYPE_MAKE_SEND_ONCE"; break;
1573 printf("%s\t%p\t%-20s\t%u\n", desc
, port
, type_name
, refs
);
1576 static void mach_msg_scan(mach_msg_header_t
*msg
, int clean
) {
1577 Boolean printed_header
= false;
1579 * The msgh_local_port field doesn't hold a port right.
1580 * The receive operation consumes the destination port right.
1582 if (MACH_PORT_NULL
!= msg
->msgh_remote_port
) {
1583 if (! printed_header
) print_msg_scan_header();
1584 printed_header
= true;
1585 print_one_port_info("msg->msgh_remote_port", msg
->msgh_remote_port
, MACH_MSGH_BITS_REMOTE(msg
->msgh_bits
));
1587 if (msg
->msgh_bits
& MACH_MSGH_BITS_COMPLEX
) {
1588 mach_msg_body_t
*body
= (mach_msg_body_t
*) (msg
+ 1);
1589 mach_msg_descriptor_t
*saddr
= (mach_msg_descriptor_t
*) ((mach_msg_base_t
*) msg
+ 1);
1590 mach_msg_descriptor_t
*eaddr
= saddr
+ body
->msgh_descriptor_count
;
1591 for ( ; saddr
< eaddr
; saddr
++) {
1592 switch (saddr
->type
.type
) {
1593 case MACH_MSG_PORT_DESCRIPTOR
:;
1594 mach_msg_port_descriptor_t
*dsc
= &saddr
->port
;
1595 if (! printed_header
) print_msg_scan_header();
1596 printed_header
= true;
1597 print_one_port_info("port in body", dsc
->name
, dsc
->disposition
);
1598 // if (clean) mach_port_deallocate(mach_task_self(), dsc->name);
1600 case MACH_MSG_OOL_PORTS_DESCRIPTOR
:;
1601 mach_msg_ool_ports_descriptor_t
*dsc2
= &saddr
->ool_ports
;
1602 mach_port_t
*ports
= (mach_port_t
*) dsc2
->address
;
1603 for (mach_msg_type_number_t j
= 0; j
< dsc2
->count
; j
++, ports
++) {
1604 if (! printed_header
) print_msg_scan_header();
1605 printed_header
= true;
1606 print_one_port_info("port in OOL ports", *ports
, dsc2
->disposition
);
1615 /* rl is unlocked, rlm locked on entrance and exit */
1616 static int32_t __CFRunLoopRun(CFRunLoopRef rl
, CFRunLoopModeRef rlm
, CFTimeInterval seconds
, Boolean stopAfterHandle
, Boolean waitIfEmpty
) { /* DOES CALLOUT */
1618 #if DEPLOYMENT_TARGET_MACOSX
1619 mach_port_name_t timeoutPort
= MACH_PORT_NULL
;
1620 Boolean timeoutPortAdded
= false;
1622 Boolean poll
= false;
1623 Boolean firstPass
= true;
1625 if (__CFRunLoopIsStopped(rl
)) {
1626 return kCFRunLoopRunStopped
;
1627 } else if (rlm
->_stopped
) {
1628 rlm
->_stopped
= false;
1629 return kCFRunLoopRunStopped
;
1631 if (seconds
<= 0.0) {
1633 } else if (3.1556952e+9 < seconds
) {
1634 termTSR
= LLONG_MAX
;
1636 termTSR
= (int64_t)__CFReadTSR() + __CFTimeIntervalToTSR(seconds
);
1637 #if DEPLOYMENT_TARGET_MACOSX
1638 timeoutPort
= mk_timer_create();
1639 mk_timer_arm(timeoutPort
, __CFUInt64ToAbsoluteTime(termTSR
));
1642 if (seconds
<= 0.0) {
1645 if (rl
== CFRunLoopGetMain()) _LastMainWaitSet
= CFPORT_NULL
;
1647 __CFPortSet waitSet
= CFPORT_NULL
;
1648 waitSet
= CFPORT_NULL
;
1649 Boolean destroyWaitSet
= false;
1650 CFRunLoopSourceRef rls
;
1651 #if DEPLOYMENT_TARGET_MACOSX
1652 mach_msg_header_t
*msg
;
1654 uint8_t buffer
[1024 + 80] = {0}; // large enough for 1k of inline payload; must be zeroed for GC
1656 CFArrayRef timersToCall
= NULL
;
1658 int32_t returnValue
= 0;
1659 Boolean sourceHandledThisLoop
= false;
1661 __CFRunLoopDoObservers(rl
, rlm
, kCFRunLoopBeforeTimers
);
1662 __CFRunLoopDoObservers(rl
, rlm
, kCFRunLoopBeforeSources
);
1664 sourceHandledThisLoop
= __CFRunLoopDoSources0(rl
, rlm
, stopAfterHandle
);
1666 if (sourceHandledThisLoop
) {
1671 __CFRunLoopDoObservers(rl
, rlm
, kCFRunLoopBeforeWaiting
);
1672 __CFRunLoopSetSleeping(rl
);
1674 if (NULL
!= rlm
->_submodes
) {
1675 // !!! what do we do if this doesn't succeed?
1676 waitSet
= __CFPortSetAllocate();
1677 if (CFPORT_NULL
== waitSet
) HALT
;
1678 __CFRunLoopModeUnlock(rlm
);
1679 __CFRunLoopLock(rl
);
1680 __CFRunLoopModeLock(rlm
);
1681 __CFRunLoopModeAddPortsToPortSet(rl
, rlm
, waitSet
);
1682 __CFRunLoopUnlock(rl
);
1683 #if DEPLOYMENT_TARGET_MACOSX
1684 if (CFPORT_NULL
!= timeoutPort
) {
1685 __CFPortSetInsert(timeoutPort
, waitSet
);
1688 destroyWaitSet
= true;
1690 waitSet
= rlm
->_portSet
;
1691 #if DEPLOYMENT_TARGET_MACOSX
1692 if (!timeoutPortAdded
&& CFPORT_NULL
!= timeoutPort
) {
1693 __CFPortSetInsert(timeoutPort
, waitSet
);
1694 timeoutPortAdded
= true;
1698 if (rl
== CFRunLoopGetMain()) _LastMainWaitSet
= waitSet
;
1699 __CFRunLoopModeUnlock(rlm
);
1701 #if DEPLOYMENT_TARGET_MACOSX
1702 msg
= (mach_msg_header_t
*)buffer
;
1703 msg
->msgh_size
= sizeof(buffer
);
1705 /* In that sleep of death what nightmares may come ... */
1708 msg
->msgh_local_port
= waitSet
;
1709 msg
->msgh_remote_port
= MACH_PORT_NULL
;
1711 ret
= mach_msg(msg
, MACH_RCV_MSG
|MACH_RCV_LARGE
|(poll
? MACH_RCV_TIMEOUT
: 0)|MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0
)|MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT
), 0, msg
->msgh_size
, waitSet
, 0, MACH_PORT_NULL
);
1712 if (MACH_RCV_TOO_LARGE
== ret
) {
1713 uint32_t newSize
= round_msg(msg
->msgh_size
) + sizeof(mach_msg_audit_trailer_t
);
1714 if (msg
== (mach_msg_header_t
*)buffer
) msg
= NULL
;
1715 msg
= CFAllocatorReallocate(kCFAllocatorSystemDefault
, msg
, newSize
, 0);
1716 msg
->msgh_size
= newSize
;
1718 } else if (MACH_RCV_TIMED_OUT
== ret
) {
1719 // timeout, for poll
1720 if (msg
!= (mach_msg_header_t
*)buffer
) CFAllocatorDeallocate(kCFAllocatorSystemDefault
, msg
);
1722 } else if (MACH_MSG_SUCCESS
!= ret
) {
1725 #elif defined(__WIN32__)
1726 DWORD waitResult
= WAIT_TIMEOUT
;
1727 HANDLE handleBuf
[MAXIMUM_WAIT_OBJECTS
];
1729 uint32_t handleCount
;
1730 Boolean freeHandles
;
1731 if (destroyWaitSet
) {
1732 // wait set is a local, no one else could modify it, no need to copy handles
1733 handles
= waitSet
->handles
;
1734 handleCount
= waitSet
->used
;
1735 freeHandles
= FALSE
;
1737 // copy out the handles to be safe from other threads at work
1738 handles
= __CFPortSetGetPorts(waitSet
, handleBuf
, MAXIMUM_WAIT_OBJECTS
, &handleCount
);
1739 freeHandles
= (handles
!= handleBuf
);
1741 // should msgQMask be an OR'ing of this and all submodes' masks?
1742 if (0 == GetQueueStatus(rlm
->_msgQMask
)) {
1747 __CFRunLoopModeLock(rlm
);
1748 int64_t nextStop
= __CFRunLoopGetNextTimerFireTSR(rl
, rlm
);
1751 else if (nextStop
> termTSR
)
1753 // else the next stop is dictated by the next timer
1754 int64_t timeoutTSR
= nextStop
- __CFReadTSR();
1758 CFTimeInterval timeoutCF
= __CFTSRToTimeInterval(timeoutTSR
) * 1000;
1759 if (timeoutCF
> MAXDWORD
)
1762 timeout
= timeoutCF
;
1765 if (_LogCFRunLoop
) { CFLog(kCFLogLevelDebug
, CFSTR("%p (%s)- about to wait for %d objects, wakeupport is %p"), CFRunLoopGetCurrent(), *_CFGetProgname(), handleCount
, rl
->_wakeUpPort
); }
1766 if (_LogCFRunLoop
) { CFLog(kCFLogLevelDebug
, CFSTR("All RLM sources = %@"), rlm
->_sources
); }
1767 waitResult
= MsgWaitForMultipleObjects(__CFMin(handleCount
, MAXIMUM_WAIT_OBJECTS
), handles
, false, timeout
, rlm
->_msgQMask
);
1768 if (_LogCFRunLoop
) { CFLog(kCFLogLevelDebug
, CFSTR("%p (%s)- waitResult was %d"), CFRunLoopGetCurrent(), *_CFGetProgname(), waitResult
); }
1770 ResetEvent(rl
->_wakeUpPort
);
1772 if (destroyWaitSet
) {
1773 __CFPortSetFree(waitSet
);
1774 if (rl
== CFRunLoopGetMain()) _LastMainWaitSet
= 0;
1776 __CFRunLoopLock(rl
);
1777 __CFRunLoopModeLock(rlm
);
1778 __CFRunLoopUnlock(rl
);
1780 __CFRunLoopUnsetSleeping(rl
);
1781 __CFRunLoopDoObservers(rl
, rlm
, kCFRunLoopAfterWaiting
);
1784 __CFRunLoopModeUnlock(rlm
);
1785 __CFRunLoopLock(rl
);
1786 __CFRunLoopModeLock(rlm
);
1788 __CFPort livePort
= CFPORT_NULL
;
1789 #if DEPLOYMENT_TARGET_MACOSX
1791 livePort
= msg
->msgh_local_port
;
1793 #elif defined(__WIN32__)
1794 CFAssert2(waitResult
!= WAIT_FAILED
, __kCFLogAssertion
, "%s(): error %d from MsgWaitForMultipleObjects", __PRETTY_FUNCTION__
, GetLastError());
1795 if (waitResult
== WAIT_TIMEOUT
) {
1796 // do nothing, just return to caller
1797 } else if (waitResult
>= WAIT_OBJECT_0
&& waitResult
< WAIT_OBJECT_0
+handleCount
) {
1798 // a handle was signalled
1799 livePort
= handles
[waitResult
-WAIT_OBJECT_0
];
1800 if (_LogCFRunLoop
) { CFLog(kCFLogLevelDebug
, CFSTR("%p (%s)- Resetting event %p"), CFRunLoopGetCurrent(), *_CFGetProgname(), livePort
); }
1801 } else if (waitResult
== WAIT_OBJECT_0
+handleCount
) {
1802 // windows message received - the CFWindowsMessageQueue will pick this up when
1803 // the v0 RunLoopSources get their chance
1804 } else if (waitResult
>= WAIT_ABANDONED_0
&& waitResult
< WAIT_ABANDONED_0
+handleCount
) {
1805 // an "abandoned mutex object"
1806 livePort
= handles
[waitResult
-WAIT_ABANDONED_0
];
1808 CFAssert2(waitResult
== WAIT_FAILED
, __kCFLogAssertion
, "%s(): unexpected result from MsgWaitForMultipleObjects: %d", __PRETTY_FUNCTION__
, waitResult
);
1811 CFAllocatorDeallocate(kCFAllocatorSystemDefault
, handles
);
1812 timersToCall
= __CFRunLoopTimersToFire(rl
, rlm
);
1815 if (CFPORT_NULL
== livePort
) {
1816 __CFRunLoopUnlock(rl
);
1817 } else if (livePort
== rl
->_wakeUpPort
) {
1819 if (_LogCFRunLoop
) { CFLog(kCFLogLevelDebug
, CFSTR("wakeupPort was signalled")); }
1820 __CFRunLoopUnlock(rl
);
1822 #if DEPLOYMENT_TARGET_MACOSX
1823 else if (livePort
== timeoutPort
) {
1824 returnValue
= kCFRunLoopRunTimedOut
;
1825 __CFRunLoopUnlock(rl
);
1826 } else if (NULL
!= (rls
= __CFRunLoopModeFindSourceForMachPort(rl
, rlm
, livePort
))) {
1827 mach_msg_header_t
*reply
= NULL
;
1828 __CFRunLoopUnlock(rl
);
1829 // mach_msg_scan(msg, 0);
1830 if (__CFRunLoopDoSource1(rl
, rlm
, rls
, msg
, msg
->msgh_size
, &reply
)) {
1831 sourceHandledThisLoop
= true;
1833 // mach_msg_scan(msg, 1);
1834 if (NULL
!= reply
) {
1835 ret
= mach_msg(reply
, MACH_SEND_MSG
, reply
->msgh_size
, 0, MACH_PORT_NULL
, 0, MACH_PORT_NULL
);
1836 //#warning CF: what should be done with the return value?
1837 CFAllocatorDeallocate(kCFAllocatorSystemDefault
, reply
);
1840 CFRunLoopTimerRef rlt
;
1841 rlt
= __CFRunLoopModeFindTimerForMachPort(rlm
, livePort
);
1842 __CFRunLoopUnlock(rl
);
1844 __CFRunLoopDoTimer(rl
, rlm
, rlt
);
1847 if (msg
!= (mach_msg_header_t
*)buffer
) CFAllocatorDeallocate(kCFAllocatorSystemDefault
, msg
);
1849 else if (NULL
!= (rls
= __CFRunLoopModeFindSourceForMachPort(rl
, rlm
, livePort
))) {
1850 __CFRunLoopUnlock(rl
);
1851 if (_LogCFRunLoop
) { CFLog(kCFLogLevelDebug
, CFSTR("Source %@ was signalled"), rls
); }
1852 if (__CFRunLoopDoSource1(rl
, rlm
, rls
)) {
1853 sourceHandledThisLoop
= true;
1858 __CFRunLoopModeUnlock(rlm
); // locks must be taken in order
1859 __CFRunLoopLock(rl
);
1860 __CFRunLoopModeLock(rlm
);
1861 if (sourceHandledThisLoop
&& stopAfterHandle
) {
1862 returnValue
= kCFRunLoopRunHandledSource
;
1863 // If we're about to timeout, but we just did a zero-timeout poll that only found our own
1864 // internal wakeup signal on the first look at the portset, we'll go around the loop one
1865 // more time, so as not to starve a v1 source that was just added along with a runloop wakeup.
1866 } else if (0 != returnValue
|| (uint64_t)termTSR
<= __CFReadTSR()) {
1867 returnValue
= kCFRunLoopRunTimedOut
;
1868 } else if (__CFRunLoopIsStopped(rl
)) {
1869 returnValue
= kCFRunLoopRunStopped
;
1870 } else if (rlm
->_stopped
) {
1871 rlm
->_stopped
= false;
1872 returnValue
= kCFRunLoopRunStopped
;
1873 } else if (!waitIfEmpty
&& __CFRunLoopModeIsEmpty(rl
, rlm
)) {
1874 returnValue
= kCFRunLoopRunFinished
;
1876 __CFRunLoopUnlock(rl
);
1877 if (0 != returnValue
) {
1878 #if DEPLOYMENT_TARGET_MACOSX
1879 if (MACH_PORT_NULL
!= timeoutPort
) {
1880 if (!destroyWaitSet
) __CFPortSetRemove(timeoutPort
, waitSet
);
1881 mk_timer_destroy(timeoutPort
);
1890 SInt32
CFRunLoopRunSpecific(CFRunLoopRef rl
, CFStringRef modeName
, CFTimeInterval seconds
, Boolean returnAfterSourceHandled
) { /* DOES CALLOUT */
1892 if (__CFRunLoopIsDeallocating(rl
)) return kCFRunLoopRunFinished
;
1893 __CFRunLoopLock(rl
);
1894 CFRunLoopModeRef currentMode
= __CFRunLoopFindMode(rl
, modeName
, false);
1895 if (NULL
== currentMode
|| __CFRunLoopModeIsEmpty(rl
, currentMode
)) {
1896 if (currentMode
) __CFRunLoopModeUnlock(currentMode
);
1897 __CFRunLoopUnlock(rl
);
1898 return kCFRunLoopRunFinished
;
1900 uint32_t *previousStopped
= (uint32_t *)rl
->_stopped
;
1901 rl
->_stopped
= CFAllocatorAllocate(kCFAllocatorSystemDefault
, 4 * sizeof(uint32_t), 0);
1902 rl
->_stopped
[0] = 0x4346524C;
1903 rl
->_stopped
[1] = 0x4346524C; // 'CFRL'
1904 rl
->_stopped
[2] = 0x00000000; // here the value is stored
1905 rl
->_stopped
[3] = 0x4346524C;
1906 CFRunLoopModeRef previousMode
= rl
->_currentMode
;
1907 rl
->_currentMode
= currentMode
;
1908 __CFRunLoopUnlock(rl
);
1910 __CFRunLoopDoObservers(rl
, currentMode
, kCFRunLoopEntry
);
1911 result
= __CFRunLoopRun(rl
, currentMode
, seconds
, returnAfterSourceHandled
, false);
1912 __CFRunLoopDoObservers(rl
, currentMode
, kCFRunLoopExit
);
1913 __CFRunLoopModeUnlock(currentMode
);
1914 __CFRunLoopLock(rl
);
1915 CFAllocatorDeallocate(kCFAllocatorSystemDefault
, (uint32_t *)rl
->_stopped
);
1916 rl
->_stopped
= previousStopped
;
1917 rl
->_currentMode
= previousMode
;
1918 __CFRunLoopUnlock(rl
);
1922 void CFRunLoopRun(void) { /* DOES CALLOUT */
1925 result
= CFRunLoopRunSpecific(CFRunLoopGetCurrent(), kCFRunLoopDefaultMode
, 1.0e10
, false);
1927 } while (kCFRunLoopRunStopped
!= result
&& kCFRunLoopRunFinished
!= result
);
1930 SInt32
CFRunLoopRunInMode(CFStringRef modeName
, CFTimeInterval seconds
, Boolean returnAfterSourceHandled
) { /* DOES CALLOUT */
1932 return CFRunLoopRunSpecific(CFRunLoopGetCurrent(), modeName
, seconds
, returnAfterSourceHandled
);
1935 static void __CFRunLoopFindMinTimer(const void *value
, void *ctx
) {
1936 CFRunLoopTimerRef rlt
= (CFRunLoopTimerRef
)value
;
1937 if (__CFIsValid(rlt
)) {
1938 CFRunLoopTimerRef
*result
= ctx
;
1939 if (NULL
== *result
|| rlt
->_fireTSR
< (*result
)->_fireTSR
) {
1945 static int64_t __CFRunLoopGetNextTimerFireTSR(CFRunLoopRef rl
, CFRunLoopModeRef rlm
) {
1946 CFRunLoopTimerRef result
= NULL
;
1947 int64_t fireTime
= 0;
1949 if (NULL
!= rlm
->_timers
&& 0 < CFSetGetCount(rlm
->_timers
)) {
1950 __CFRunLoopTimerFireTSRLock();
1951 CFSetApplyFunction(rlm
->_timers
, (__CFRunLoopFindMinTimer
), &result
);
1953 fireTime
= result
->_fireTSR
;
1954 __CFRunLoopTimerFireTSRUnlock();
1956 if (NULL
!= rlm
->_submodes
) {
1958 for (idx
= 0, cnt
= CFArrayGetCount(rlm
->_submodes
); idx
< cnt
; idx
++) {
1959 CFStringRef modeName
= (CFStringRef
)CFArrayGetValueAtIndex(rlm
->_submodes
, idx
);
1960 CFRunLoopModeRef subrlm
;
1961 subrlm
= __CFRunLoopFindMode(rl
, modeName
, false);
1962 if (NULL
!= subrlm
) {
1963 int64_t newFireTime
= __CFRunLoopGetNextTimerFireTSR(rl
, subrlm
);
1964 __CFRunLoopModeUnlock(subrlm
);
1965 if (fireTime
== 0 || (newFireTime
!= 0 && newFireTime
< fireTime
))
1966 fireTime
= newFireTime
;
1970 __CFRunLoopModeUnlock(rlm
);
1975 CFAbsoluteTime
CFRunLoopGetNextTimerFireDate(CFRunLoopRef rl
, CFStringRef modeName
) {
1977 CFRunLoopModeRef rlm
;
1979 __CFRunLoopLock(rl
);
1980 rlm
= __CFRunLoopFindMode(rl
, modeName
, false);
1981 __CFRunLoopUnlock(rl
);
1982 fireTSR
= __CFRunLoopGetNextTimerFireTSR(rl
, rlm
);
1983 int64_t now2
= (int64_t)mach_absolute_time();
1984 CFAbsoluteTime now1
= CFAbsoluteTimeGetCurrent();
1985 return (0 == fireTSR
) ? 0.0 : (now1
+ __CFTSRToTimeInterval(fireTSR
- now2
));
1988 Boolean
CFRunLoopIsWaiting(CFRunLoopRef rl
) {
1990 return __CFRunLoopIsSleeping(rl
);
1993 void CFRunLoopWakeUp(CFRunLoopRef rl
) {
1995 #if DEPLOYMENT_TARGET_MACOSX
1997 /* We unconditionally try to send the message, since we don't want
1998 * to lose a wakeup, but the send may fail if there is already a
1999 * wakeup pending, since the queue length is 1. */
2000 ret
= __CFSendTrivialMachMessage(rl
->_wakeUpPort
, 0, MACH_SEND_TIMEOUT
, 0);
2001 if (ret
!= MACH_MSG_SUCCESS
&& ret
!= MACH_SEND_TIMED_OUT
) {
2005 SetEvent(rl
->_wakeUpPort
);
2009 void CFRunLoopStop(CFRunLoopRef rl
) {
2011 __CFRunLoopLock(rl
);
2012 __CFRunLoopSetStopped(rl
);
2013 __CFRunLoopUnlock(rl
);
2014 CFRunLoopWakeUp(rl
);
2017 CF_EXPORT
void _CFRunLoopStopMode(CFRunLoopRef rl
, CFStringRef modeName
) {
2019 CFRunLoopModeRef rlm
;
2020 __CFRunLoopLock(rl
);
2021 rlm
= __CFRunLoopFindMode(rl
, modeName
, true);
2022 __CFRunLoopUnlock(rl
);
2024 rlm
->_stopped
= true;
2025 __CFRunLoopModeUnlock(rlm
);
2027 CFRunLoopWakeUp(rl
);
2030 CF_EXPORT Boolean
_CFRunLoopModeContainsMode(CFRunLoopRef rl
, CFStringRef modeName
, CFStringRef candidateContainedName
) {
2032 CFRunLoopModeRef rlm
;
2033 if (modeName
== kCFRunLoopCommonModes
|| candidateContainedName
== kCFRunLoopCommonModes
) {
2035 } else if (CFEqual(modeName
, candidateContainedName
)) {
2038 __CFRunLoopLock(rl
);
2039 rlm
= __CFRunLoopFindMode(rl
, modeName
, true);
2040 __CFRunLoopUnlock(rl
);
2042 CFArrayRef submodes
;
2043 if (NULL
== rlm
->_submodes
) {
2044 __CFRunLoopModeUnlock(rlm
);
2047 if (CFArrayContainsValue(rlm
->_submodes
, CFRangeMake(0, CFArrayGetCount(rlm
->_submodes
)), candidateContainedName
)) {
2048 __CFRunLoopModeUnlock(rlm
);
2051 submodes
= (NULL
!= rlm
->_submodes
&& 0 < CFArrayGetCount(rlm
->_submodes
)) ? CFArrayCreateCopy(kCFAllocatorSystemDefault
, rlm
->_submodes
) : NULL
;
2052 __CFRunLoopModeUnlock(rlm
);
2053 if (NULL
!= submodes
) {
2055 for (idx
= 0, cnt
= CFArrayGetCount(submodes
); idx
< cnt
; idx
++) {
2056 CFStringRef subname
= (CFStringRef
)CFArrayGetValueAtIndex(submodes
, idx
);
2057 if (_CFRunLoopModeContainsMode(rl
, subname
, candidateContainedName
)) {
2058 CFRelease(submodes
);
2062 CFRelease(submodes
);
2068 CF_EXPORT
void _CFRunLoopAddModeToMode(CFRunLoopRef rl
, CFStringRef modeName
, CFStringRef toModeName
) {
2070 CFRunLoopModeRef rlm
;
2071 if (__CFRunLoopIsDeallocating(rl
)) return;
2072 // should really do a recursive check here, to make sure that a cycle isn't
2073 // introduced; of course, if that happens, you aren't going to get very far.
2074 if (modeName
== kCFRunLoopCommonModes
|| toModeName
== kCFRunLoopCommonModes
|| CFEqual(modeName
, toModeName
)) {
2077 __CFRunLoopLock(rl
);
2078 rlm
= __CFRunLoopFindMode(rl
, toModeName
, true);
2079 __CFRunLoopUnlock(rl
);
2081 if (NULL
== rlm
->_submodes
) {
2082 rlm
->_submodes
= CFArrayCreateMutable(CFGetAllocator(rlm
), 0, &kCFTypeArrayCallBacks
);
2084 if (!CFArrayContainsValue(rlm
->_submodes
, CFRangeMake(0, CFArrayGetCount(rlm
->_submodes
)), modeName
)) {
2085 CFArrayAppendValue(rlm
->_submodes
, modeName
);
2087 __CFRunLoopModeUnlock(rlm
);
2092 CF_EXPORT
void _CFRunLoopRemoveModeFromMode(CFRunLoopRef rl
, CFStringRef modeName
, CFStringRef fromModeName
) {
2094 CFRunLoopModeRef rlm
;
2095 // should really do a recursive check here, to make sure that a cycle isn't
2096 // introduced; of course, if that happens, you aren't going to get very far.
2097 if (modeName
== kCFRunLoopCommonModes
|| fromModeName
== kCFRunLoopCommonModes
|| CFEqual(modeName
, fromModeName
)) {
2100 __CFRunLoopLock(rl
);
2101 rlm
= __CFRunLoopFindMode(rl
, fromModeName
, true);
2102 __CFRunLoopUnlock(rl
);
2104 if (NULL
!= rlm
->_submodes
) {
2105 CFIndex idx
, cnt
= CFArrayGetCount(rlm
->_submodes
);
2106 idx
= CFArrayGetFirstIndexOfValue(rlm
->_submodes
, CFRangeMake(0, cnt
), modeName
);
2107 if (0 <= idx
) CFArrayRemoveValueAtIndex(rlm
->_submodes
, idx
);
2109 __CFRunLoopModeUnlock(rlm
);
2114 Boolean
CFRunLoopContainsSource(CFRunLoopRef rl
, CFRunLoopSourceRef rls
, CFStringRef modeName
) {
2116 CFRunLoopModeRef rlm
;
2117 Boolean hasValue
= false;
2118 __CFRunLoopLock(rl
);
2119 if (modeName
== kCFRunLoopCommonModes
) {
2120 if (NULL
!= rl
->_commonModeItems
) {
2121 hasValue
= CFSetContainsValue(rl
->_commonModeItems
, rls
);
2123 __CFRunLoopUnlock(rl
);
2125 rlm
= __CFRunLoopFindMode(rl
, modeName
, false);
2126 __CFRunLoopUnlock(rl
);
2127 if (NULL
!= rlm
&& NULL
!= rlm
->_sources
) {
2128 hasValue
= CFSetContainsValue(rlm
->_sources
, rls
);
2129 __CFRunLoopModeUnlock(rlm
);
2130 } else if (NULL
!= rlm
) {
2131 __CFRunLoopModeUnlock(rlm
);
2137 void CFRunLoopAddSource(CFRunLoopRef rl
, CFRunLoopSourceRef rls
, CFStringRef modeName
) { /* DOES CALLOUT */
2139 CFRunLoopModeRef rlm
;
2140 if (__CFRunLoopIsDeallocating(rl
)) return;
2141 if (!__CFIsValid(rls
)) return;
2142 __CFRunLoopLock(rl
);
2143 if (modeName
== kCFRunLoopCommonModes
) {
2144 CFSetRef set
= rl
->_commonModes
? CFSetCreateCopy(kCFAllocatorSystemDefault
, rl
->_commonModes
) : NULL
;
2145 if (NULL
== rl
->_commonModeItems
) {
2146 rl
->_commonModeItems
= CFSetCreateMutable(CFGetAllocator(rl
), 0, &kCFTypeSetCallBacks
);
2147 _CFSetSetCapacity(rl
->_commonModeItems
, 20);
2149 CFSetAddValue(rl
->_commonModeItems
, rls
);
2150 __CFRunLoopUnlock(rl
);
2152 CFTypeRef context
[2] = {rl
, rls
};
2153 /* add new item to all common-modes */
2154 CFSetApplyFunction(set
, (__CFRunLoopAddItemToCommonModes
), (void *)context
);
2158 rlm
= __CFRunLoopFindMode(rl
, modeName
, true);
2159 __CFRunLoopUnlock(rl
);
2160 if (NULL
!= rlm
&& NULL
== rlm
->_sources
) {
2161 rlm
->_sources
= CFSetCreateMutable(CFGetAllocator(rlm
), 0, &kCFTypeSetCallBacks
);
2162 _CFSetSetCapacity(rlm
->_sources
, 10);
2164 if (NULL
!= rlm
&& !CFSetContainsValue(rlm
->_sources
, rls
)) {
2165 CFSetAddValue(rlm
->_sources
, rls
);
2166 __CFRunLoopModeUnlock(rlm
);
2167 __CFRunLoopSourceSchedule(rls
, rl
, rlm
); /* DOES CALLOUT */
2168 } else if (NULL
!= rlm
) {
2169 __CFRunLoopModeUnlock(rlm
);
2174 void CFRunLoopRemoveSource(CFRunLoopRef rl
, CFRunLoopSourceRef rls
, CFStringRef modeName
) { /* DOES CALLOUT */
2176 CFRunLoopModeRef rlm
;
2177 __CFRunLoopLock(rl
);
2178 if (modeName
== kCFRunLoopCommonModes
) {
2179 if (NULL
!= rl
->_commonModeItems
&& CFSetContainsValue(rl
->_commonModeItems
, rls
)) {
2180 CFSetRef set
= rl
->_commonModes
? CFSetCreateCopy(kCFAllocatorSystemDefault
, rl
->_commonModes
) : NULL
;
2181 CFSetRemoveValue(rl
->_commonModeItems
, rls
);
2182 __CFRunLoopUnlock(rl
);
2184 CFTypeRef context
[2] = {rl
, rls
};
2185 /* remove new item from all common-modes */
2186 CFSetApplyFunction(set
, (__CFRunLoopRemoveItemFromCommonModes
), (void *)context
);
2190 __CFRunLoopUnlock(rl
);
2193 rlm
= __CFRunLoopFindMode(rl
, modeName
, false);
2194 __CFRunLoopUnlock(rl
);
2195 if (NULL
!= rlm
&& NULL
!= rlm
->_sources
&& CFSetContainsValue(rlm
->_sources
, rls
)) {
2197 CFSetRemoveValue(rlm
->_sources
, rls
);
2198 __CFRunLoopModeUnlock(rlm
);
2199 __CFRunLoopSourceCancel(rls
, rl
, rlm
); /* DOES CALLOUT */
2201 } else if (NULL
!= rlm
) {
2202 __CFRunLoopModeUnlock(rlm
);
2207 static void __CFRunLoopRemoveSourcesFromCommonMode(const void *value
, void *ctx
) {
2208 CFStringRef modeName
= (CFStringRef
)value
;
2209 CFRunLoopRef rl
= (CFRunLoopRef
)ctx
;
2210 __CFRunLoopRemoveAllSources(rl
, modeName
);
2213 static void __CFRunLoopRemoveSourceFromMode(const void *value
, void *ctx
) {
2214 CFRunLoopSourceRef rls
= (CFRunLoopSourceRef
)value
;
2215 CFRunLoopRef rl
= (CFRunLoopRef
)(((CFTypeRef
*)ctx
)[0]);
2216 CFStringRef modeName
= (CFStringRef
)(((CFTypeRef
*)ctx
)[1]);
2217 CFRunLoopRemoveSource(rl
, rls
, modeName
);
2220 static void __CFRunLoopRemoveAllSources(CFRunLoopRef rl
, CFStringRef modeName
) {
2222 CFRunLoopModeRef rlm
;
2223 __CFRunLoopLock(rl
);
2224 if (modeName
== kCFRunLoopCommonModes
) {
2225 if (NULL
!= rl
->_commonModeItems
) {
2226 CFSetRef set
= rl
->_commonModes
? CFSetCreateCopy(kCFAllocatorSystemDefault
, rl
->_commonModes
) : NULL
;
2227 __CFRunLoopUnlock(rl
);
2229 CFSetApplyFunction(set
, (__CFRunLoopRemoveSourcesFromCommonMode
), (void *)rl
);
2233 __CFRunLoopUnlock(rl
);
2236 rlm
= __CFRunLoopFindMode(rl
, modeName
, false);
2237 __CFRunLoopUnlock(rl
);
2238 if (NULL
!= rlm
&& NULL
!= rlm
->_sources
) {
2239 CFSetRef set
= CFSetCreateCopy(kCFAllocatorSystemDefault
, rlm
->_sources
);
2240 __CFRunLoopModeUnlock(rlm
);
2241 CFTypeRef context
[2] = {rl
, modeName
};
2242 CFSetApplyFunction(set
, (__CFRunLoopRemoveSourceFromMode
), (void *)context
);
2244 } else if (NULL
!= rlm
) {
2245 __CFRunLoopModeUnlock(rlm
);
2250 Boolean
CFRunLoopContainsObserver(CFRunLoopRef rl
, CFRunLoopObserverRef rlo
, CFStringRef modeName
) {
2252 CFRunLoopModeRef rlm
;
2253 Boolean hasValue
= false;
2254 __CFRunLoopLock(rl
);
2255 if (modeName
== kCFRunLoopCommonModes
) {
2256 if (NULL
!= rl
->_commonModeItems
) {
2257 hasValue
= CFSetContainsValue(rl
->_commonModeItems
, rlo
);
2259 __CFRunLoopUnlock(rl
);
2261 rlm
= __CFRunLoopFindMode(rl
, modeName
, false);
2262 __CFRunLoopUnlock(rl
);
2263 if (NULL
!= rlm
&& NULL
!= rlm
->_observers
) {
2264 hasValue
= CFSetContainsValue(rlm
->_observers
, rlo
);
2265 __CFRunLoopModeUnlock(rlm
);
2266 } else if (NULL
!= rlm
) {
2267 __CFRunLoopModeUnlock(rlm
);
2273 void CFRunLoopAddObserver(CFRunLoopRef rl
, CFRunLoopObserverRef rlo
, CFStringRef modeName
) {
2275 CFRunLoopModeRef rlm
;
2276 if (__CFRunLoopIsDeallocating(rl
)) return;
2277 if (!__CFIsValid(rlo
) || (NULL
!= rlo
->_runLoop
&& rlo
->_runLoop
!= rl
)) return;
2278 __CFRunLoopLock(rl
);
2279 if (modeName
== kCFRunLoopCommonModes
) {
2280 CFSetRef set
= rl
->_commonModes
? CFSetCreateCopy(kCFAllocatorSystemDefault
, rl
->_commonModes
) : NULL
;
2281 if (NULL
== rl
->_commonModeItems
) {
2282 rl
->_commonModeItems
= CFSetCreateMutable(CFGetAllocator(rl
), 0, &kCFTypeSetCallBacks
);
2284 CFSetAddValue(rl
->_commonModeItems
, rlo
);
2285 __CFRunLoopUnlock(rl
);
2287 CFTypeRef context
[2] = {rl
, rlo
};
2288 /* add new item to all common-modes */
2289 CFSetApplyFunction(set
, (__CFRunLoopAddItemToCommonModes
), (void *)context
);
2293 rlm
= __CFRunLoopFindMode(rl
, modeName
, true);
2294 __CFRunLoopUnlock(rl
);
2295 if (NULL
!= rlm
&& NULL
== rlm
->_observers
) {
2296 rlm
->_observers
= CFSetCreateMutable(CFGetAllocator(rlm
), 0, &kCFTypeSetCallBacks
);
2298 if (NULL
!= rlm
&& !CFSetContainsValue(rlm
->_observers
, rlo
)) {
2299 CFSetAddValue(rlm
->_observers
, rlo
);
2300 __CFRunLoopModeUnlock(rlm
);
2301 __CFRunLoopObserverSchedule(rlo
, rl
, rlm
);
2302 } else if (NULL
!= rlm
) {
2303 __CFRunLoopModeUnlock(rlm
);
2308 void CFRunLoopRemoveObserver(CFRunLoopRef rl
, CFRunLoopObserverRef rlo
, CFStringRef modeName
) {
2310 CFRunLoopModeRef rlm
;
2311 __CFRunLoopLock(rl
);
2312 if (modeName
== kCFRunLoopCommonModes
) {
2313 if (NULL
!= rl
->_commonModeItems
&& CFSetContainsValue(rl
->_commonModeItems
, rlo
)) {
2314 CFSetRef set
= rl
->_commonModes
? CFSetCreateCopy(kCFAllocatorSystemDefault
, rl
->_commonModes
) : NULL
;
2315 CFSetRemoveValue(rl
->_commonModeItems
, rlo
);
2316 __CFRunLoopUnlock(rl
);
2318 CFTypeRef context
[2] = {rl
, rlo
};
2319 /* remove new item from all common-modes */
2320 CFSetApplyFunction(set
, (__CFRunLoopRemoveItemFromCommonModes
), (void *)context
);
2324 __CFRunLoopUnlock(rl
);
2327 rlm
= __CFRunLoopFindMode(rl
, modeName
, false);
2328 __CFRunLoopUnlock(rl
);
2329 if (NULL
!= rlm
&& NULL
!= rlm
->_observers
&& CFSetContainsValue(rlm
->_observers
, rlo
)) {
2331 CFSetRemoveValue(rlm
->_observers
, rlo
);
2332 __CFRunLoopModeUnlock(rlm
);
2333 __CFRunLoopObserverCancel(rlo
, rl
, rlm
);
2335 } else if (NULL
!= rlm
) {
2336 __CFRunLoopModeUnlock(rlm
);
2341 Boolean
CFRunLoopContainsTimer(CFRunLoopRef rl
, CFRunLoopTimerRef rlt
, CFStringRef modeName
) {
2343 CFRunLoopModeRef rlm
;
2344 Boolean hasValue
= false;
2345 __CFRunLoopLock(rl
);
2346 if (modeName
== kCFRunLoopCommonModes
) {
2347 if (NULL
!= rl
->_commonModeItems
) {
2348 hasValue
= CFSetContainsValue(rl
->_commonModeItems
, rlt
);
2350 __CFRunLoopUnlock(rl
);
2352 rlm
= __CFRunLoopFindMode(rl
, modeName
, false);
2353 __CFRunLoopUnlock(rl
);
2354 if (NULL
!= rlm
&& NULL
!= rlm
->_timers
) {
2355 hasValue
= CFSetContainsValue(rlm
->_timers
, rlt
);
2356 __CFRunLoopModeUnlock(rlm
);
2357 } else if (NULL
!= rlm
) {
2358 __CFRunLoopModeUnlock(rlm
);
2364 void CFRunLoopAddTimer(CFRunLoopRef rl
, CFRunLoopTimerRef rlt
, CFStringRef modeName
) {
2366 CFRunLoopModeRef rlm
;
2367 if (__CFRunLoopIsDeallocating(rl
)) return;
2368 if (!__CFIsValid(rlt
) || (NULL
!= rlt
->_runLoop
&& rlt
->_runLoop
!= rl
)) return;
2369 __CFRunLoopLock(rl
);
2370 if (modeName
== kCFRunLoopCommonModes
) {
2371 CFSetRef set
= rl
->_commonModes
? CFSetCreateCopy(kCFAllocatorSystemDefault
, rl
->_commonModes
) : NULL
;
2372 if (NULL
== rl
->_commonModeItems
) {
2373 rl
->_commonModeItems
= CFSetCreateMutable(CFGetAllocator(rl
), 0, &kCFTypeSetCallBacks
);
2375 CFSetAddValue(rl
->_commonModeItems
, rlt
);
2376 __CFRunLoopUnlock(rl
);
2378 CFTypeRef context
[2] = {rl
, rlt
};
2379 /* add new item to all common-modes */
2380 CFSetApplyFunction(set
, (__CFRunLoopAddItemToCommonModes
), (void *)context
);
2384 rlm
= __CFRunLoopFindMode(rl
, modeName
, true);
2385 __CFRunLoopUnlock(rl
);
2386 if (NULL
!= rlm
&& NULL
== rlm
->_timers
) {
2387 rlm
->_timers
= CFSetCreateMutable(CFGetAllocator(rlm
), 0, &kCFTypeSetCallBacks
);
2389 if (NULL
!= rlm
&& !CFSetContainsValue(rlm
->_timers
, rlt
)) {
2390 CFSetAddValue(rlm
->_timers
, rlt
);
2391 __CFRunLoopModeUnlock(rlm
);
2392 __CFRunLoopTimerSchedule(rlt
, rl
, rlm
);
2393 } else if (NULL
!= rlm
) {
2394 __CFRunLoopModeUnlock(rlm
);
2399 void CFRunLoopRemoveTimer(CFRunLoopRef rl
, CFRunLoopTimerRef rlt
, CFStringRef modeName
) {
2401 CFRunLoopModeRef rlm
;
2402 __CFRunLoopLock(rl
);
2403 if (modeName
== kCFRunLoopCommonModes
) {
2404 if (NULL
!= rl
->_commonModeItems
&& CFSetContainsValue(rl
->_commonModeItems
, rlt
)) {
2405 CFSetRef set
= rl
->_commonModes
? CFSetCreateCopy(kCFAllocatorSystemDefault
, rl
->_commonModes
) : NULL
;
2406 CFSetRemoveValue(rl
->_commonModeItems
, rlt
);
2407 __CFRunLoopUnlock(rl
);
2409 CFTypeRef context
[2] = {rl
, rlt
};
2410 /* remove new item from all common-modes */
2411 CFSetApplyFunction(set
, (__CFRunLoopRemoveItemFromCommonModes
), (void *)context
);
2415 __CFRunLoopUnlock(rl
);
2418 rlm
= __CFRunLoopFindMode(rl
, modeName
, false);
2419 __CFRunLoopUnlock(rl
);
2420 if (NULL
!= rlm
&& NULL
!= rlm
->_timers
&& CFSetContainsValue(rlm
->_timers
, rlt
)) {
2422 CFSetRemoveValue(rlm
->_timers
, rlt
);
2423 __CFRunLoopModeUnlock(rlm
);
2424 __CFRunLoopTimerCancel(rlt
, rl
, rlm
);
2426 } else if (NULL
!= rlm
) {
2427 __CFRunLoopModeUnlock(rlm
);
2433 /* CFRunLoopSource */
2435 static Boolean
__CFRunLoopSourceEqual(CFTypeRef cf1
, CFTypeRef cf2
) { /* DOES CALLOUT */
2436 CFRunLoopSourceRef rls1
= (CFRunLoopSourceRef
)cf1
;
2437 CFRunLoopSourceRef rls2
= (CFRunLoopSourceRef
)cf2
;
2438 if (rls1
== rls2
) return true;
2439 if (rls1
->_order
!= rls2
->_order
) return false;
2440 if (rls1
->_context
.version0
.version
!= rls2
->_context
.version0
.version
) return false;
2441 if (rls1
->_context
.version0
.hash
!= rls2
->_context
.version0
.hash
) return false;
2442 if (rls1
->_context
.version0
.equal
!= rls2
->_context
.version0
.equal
) return false;
2443 if (0 == rls1
->_context
.version0
.version
&& rls1
->_context
.version0
.perform
!= rls2
->_context
.version0
.perform
) return false;
2444 if (1 == rls1
->_context
.version0
.version
&& rls1
->_context
.version1
.perform
!= rls2
->_context
.version1
.perform
) return false;
2445 if (rls1
->_context
.version0
.equal
)
2446 return rls1
->_context
.version0
.equal(rls1
->_context
.version0
.info
, rls2
->_context
.version0
.info
);
2447 return (rls1
->_context
.version0
.info
== rls2
->_context
.version0
.info
);
2450 static CFHashCode
__CFRunLoopSourceHash(CFTypeRef cf
) { /* DOES CALLOUT */
2451 CFRunLoopSourceRef rls
= (CFRunLoopSourceRef
)cf
;
2452 if (rls
->_context
.version0
.hash
)
2453 return rls
->_context
.version0
.hash(rls
->_context
.version0
.info
);
2454 return (CFHashCode
)rls
->_context
.version0
.info
;
2457 static CFStringRef
__CFRunLoopSourceCopyDescription(CFTypeRef cf
) { /* DOES CALLOUT */
2458 CFRunLoopSourceRef rls
= (CFRunLoopSourceRef
)cf
;
2460 CFStringRef contextDesc
= NULL
;
2461 if (NULL
!= rls
->_context
.version0
.copyDescription
) {
2462 contextDesc
= rls
->_context
.version0
.copyDescription(rls
->_context
.version0
.info
);
2464 if (NULL
== contextDesc
) {
2465 void *addr
= rls
->_context
.version0
.version
== 0 ? (void *)rls
->_context
.version0
.perform
: (rls
->_context
.version0
.version
== 1 ? (void *)rls
->_context
.version1
.perform
: NULL
);
2466 #if DEPLOYMENT_TARGET_MACOSX
2468 const char *name
= (dladdr(addr
, &info
) && info
.dli_saddr
== addr
&& info
.dli_sname
) ? info
.dli_sname
: "???";
2469 contextDesc
= CFStringCreateWithFormat(CFGetAllocator(rls
), NULL
, CFSTR("<CFRunLoopSource context>{version = %ld, info = %p, callout = %s (%p)}"), rls
->_context
.version0
.version
, rls
->_context
.version0
.info
, name
, addr
);
2471 #error Unknown or unspecified DEPLOYMENT_TARGET
2474 result
= CFStringCreateWithFormat(CFGetAllocator(rls
), NULL
, CFSTR("<CFRunLoopSource %p [%p]>{locked = %s, signalled = %s, valid = %s, order = %d, context = %@}"), cf
, CFGetAllocator(rls
), lockCount(rls
->_lock
) ? "Yes" : "No", __CFRunLoopSourceIsSignaled(rls
) ? "Yes" : "No", __CFIsValid(rls
) ? "Yes" : "No", rls
->_order
, contextDesc
);
2475 CFRelease(contextDesc
);
2479 static void __CFRunLoopSourceDeallocate(CFTypeRef cf
) { /* DOES CALLOUT */
2480 CFRunLoopSourceRef rls
= (CFRunLoopSourceRef
)cf
;
2481 CFRunLoopSourceInvalidate(rls
);
2482 if (rls
->_context
.version0
.release
) {
2483 rls
->_context
.version0
.release(rls
->_context
.version0
.info
);
2487 static const CFRuntimeClass __CFRunLoopSourceClass
= {
2488 _kCFRuntimeScannedObject
,
2492 __CFRunLoopSourceDeallocate
,
2493 __CFRunLoopSourceEqual
,
2494 __CFRunLoopSourceHash
,
2496 __CFRunLoopSourceCopyDescription
2499 __private_extern__
void __CFRunLoopSourceInitialize(void) {
2500 __kCFRunLoopSourceTypeID
= _CFRuntimeRegisterClass(&__CFRunLoopSourceClass
);
2503 CFTypeID
CFRunLoopSourceGetTypeID(void) {
2504 return __kCFRunLoopSourceTypeID
;
2507 CFRunLoopSourceRef
CFRunLoopSourceCreate(CFAllocatorRef allocator
, CFIndex order
, CFRunLoopSourceContext
*context
) {
2509 CFRunLoopSourceRef memory
;
2511 if (NULL
== context
) HALT
;
2512 size
= sizeof(struct __CFRunLoopSource
) - sizeof(CFRuntimeBase
);
2513 memory
= (CFRunLoopSourceRef
)_CFRuntimeCreateInstance(allocator
, __kCFRunLoopSourceTypeID
, size
, NULL
);
2514 if (NULL
== memory
) {
2517 __CFSetValid(memory
);
2518 __CFRunLoopSourceUnsetSignaled(memory
);
2519 CF_SPINLOCK_INIT_FOR_STRUCTS(memory
->_lock
);
2521 memory
->_order
= order
;
2522 memory
->_runLoops
= NULL
;
2524 switch (context
->version
) {
2526 size
= sizeof(CFRunLoopSourceContext
);
2529 size
= sizeof(CFRunLoopSourceContext1
);
2531 #if DEPLOYMENT_TARGET_MACOSX
2533 size
= sizeof(CFRunLoopSourceContext2
);
2537 CF_WRITE_BARRIER_MEMMOVE(&memory
->_context
, context
, size
);
2538 if (context
->retain
) {
2539 memory
->_context
.version0
.info
= (void *)context
->retain(context
->info
);
2544 CFIndex
CFRunLoopSourceGetOrder(CFRunLoopSourceRef rls
) {
2546 __CFGenericValidateType(rls
, __kCFRunLoopSourceTypeID
);
2550 static void __CFRunLoopSourceRemoveFromRunLoop(const void *value
, void *context
) {
2551 CFRunLoopRef rl
= (CFRunLoopRef
)value
;
2552 CFTypeRef
*params
= context
;
2553 CFRunLoopSourceRef rls
= (CFRunLoopSourceRef
)params
[0];
2556 if (rl
== params
[1]) return;
2557 array
= CFRunLoopCopyAllModes(rl
);
2558 for (idx
= CFArrayGetCount(array
); idx
--;) {
2559 CFStringRef modeName
= CFArrayGetValueAtIndex(array
, idx
);
2560 CFRunLoopRemoveSource(rl
, rls
, modeName
);
2562 CFRunLoopRemoveSource(rl
, rls
, kCFRunLoopCommonModes
);
2567 void CFRunLoopSourceInvalidate(CFRunLoopSourceRef rls
) {
2569 __CFGenericValidateType(rls
, __kCFRunLoopSourceTypeID
);
2571 __CFRunLoopSourceLock(rls
);
2572 if (__CFIsValid(rls
)) {
2573 __CFUnsetValid(rls
);
2574 __CFRunLoopSourceUnsetSignaled(rls
);
2575 if (NULL
!= rls
->_runLoops
) {
2576 CFTypeRef params
[2] = {rls
, NULL
};
2577 CFBagRef bag
= CFBagCreateCopy(kCFAllocatorSystemDefault
, rls
->_runLoops
);
2578 CFRelease(rls
->_runLoops
);
2579 rls
->_runLoops
= NULL
;
2580 __CFRunLoopSourceUnlock(rls
);
2581 CFBagApplyFunction(bag
, (__CFRunLoopSourceRemoveFromRunLoop
), params
);
2584 __CFRunLoopSourceUnlock(rls
);
2586 /* for hashing- and equality-use purposes, can't actually release the context here */
2588 __CFRunLoopSourceUnlock(rls
);
2593 Boolean
CFRunLoopSourceIsValid(CFRunLoopSourceRef rls
) {
2595 __CFGenericValidateType(rls
, __kCFRunLoopSourceTypeID
);
2596 return __CFIsValid(rls
);
2599 void CFRunLoopSourceGetContext(CFRunLoopSourceRef rls
, CFRunLoopSourceContext
*context
) {
2601 __CFGenericValidateType(rls
, __kCFRunLoopSourceTypeID
);
2602 CFAssert1(0 == context
->version
|| 1 == context
->version
, __kCFLogAssertion
, "%s(): context version not initialized to 0 or 1", __PRETTY_FUNCTION__
);
2604 switch (context
->version
) {
2606 size
= sizeof(CFRunLoopSourceContext
);
2609 size
= sizeof(CFRunLoopSourceContext1
);
2611 #if DEPLOYMENT_TARGET_MACOSX
2613 size
= sizeof(CFRunLoopSourceContext2
);
2617 memmove(context
, &rls
->_context
, size
);
2620 void CFRunLoopSourceSignal(CFRunLoopSourceRef rls
) {
2622 __CFRunLoopSourceLock(rls
);
2623 if (__CFIsValid(rls
)) {
2624 __CFRunLoopSourceSetSignaled(rls
);
2626 __CFRunLoopSourceUnlock(rls
);
2629 Boolean
CFRunLoopSourceIsSignalled(CFRunLoopSourceRef rls
) {
2631 __CFRunLoopSourceLock(rls
);
2632 Boolean ret
= __CFRunLoopSourceIsSignaled(rls
) ? true : false;
2633 __CFRunLoopSourceUnlock(rls
);
2637 /* CFRunLoopObserver */
2639 static CFStringRef
__CFRunLoopObserverCopyDescription(CFTypeRef cf
) { /* DOES CALLOUT */
2640 CFRunLoopObserverRef rlo
= (CFRunLoopObserverRef
)cf
;
2642 CFStringRef contextDesc
= NULL
;
2643 if (NULL
!= rlo
->_context
.copyDescription
) {
2644 contextDesc
= rlo
->_context
.copyDescription(rlo
->_context
.info
);
2647 contextDesc
= CFStringCreateWithFormat(CFGetAllocator(rlo
), NULL
, CFSTR("<CFRunLoopObserver context %p>"), rlo
->_context
.info
);
2649 #if DEPLOYMENT_TARGET_MACOSX
2650 void *addr
= rlo
->_callout
;
2652 const char *name
= (dladdr(addr
, &info
) && info
.dli_saddr
== addr
&& info
.dli_sname
) ? info
.dli_sname
: "???";
2653 result
= CFStringCreateWithFormat(CFGetAllocator(rlo
), NULL
, CFSTR("<CFRunLoopObserver %p [%p]>{locked = %s, valid = %s, activities = 0x%x, repeats = %s, order = %d, callout = %s (%p), context = %@}"), cf
, CFGetAllocator(rlo
), lockCount(rlo
->_lock
) ? "Yes" : "No", __CFIsValid(rlo
) ? "Yes" : "No", rlo
->_activities
, __CFRunLoopObserverRepeats(rlo
) ? "Yes" : "No", rlo
->_order
, name
, addr
, contextDesc
);
2655 #error Unknown or unspecified DEPLOYMENT_TARGET
2657 CFRelease(contextDesc
);
2661 static void __CFRunLoopObserverDeallocate(CFTypeRef cf
) { /* DOES CALLOUT */
2662 CFRunLoopObserverRef rlo
= (CFRunLoopObserverRef
)cf
;
2663 CFRunLoopObserverInvalidate(rlo
);
2666 static const CFRuntimeClass __CFRunLoopObserverClass
= {
2668 "CFRunLoopObserver",
2671 __CFRunLoopObserverDeallocate
,
2675 __CFRunLoopObserverCopyDescription
2678 __private_extern__
void __CFRunLoopObserverInitialize(void) {
2679 __kCFRunLoopObserverTypeID
= _CFRuntimeRegisterClass(&__CFRunLoopObserverClass
);
2682 CFTypeID
CFRunLoopObserverGetTypeID(void) {
2683 return __kCFRunLoopObserverTypeID
;
2686 CFRunLoopObserverRef
CFRunLoopObserverCreate(CFAllocatorRef allocator
, CFOptionFlags activities
, Boolean repeats
, CFIndex order
, CFRunLoopObserverCallBack callout
, CFRunLoopObserverContext
*context
) {
2688 CFRunLoopObserverRef memory
;
2690 size
= sizeof(struct __CFRunLoopObserver
) - sizeof(CFRuntimeBase
);
2691 memory
= (CFRunLoopObserverRef
)_CFRuntimeCreateInstance(allocator
, __kCFRunLoopObserverTypeID
, size
, NULL
);
2692 if (NULL
== memory
) {
2695 __CFSetValid(memory
);
2696 __CFRunLoopObserverUnsetFiring(memory
);
2698 __CFRunLoopObserverSetRepeats(memory
);
2700 __CFRunLoopObserverUnsetRepeats(memory
);
2702 CF_SPINLOCK_INIT_FOR_STRUCTS(memory
->_lock
);
2703 memory
->_runLoop
= NULL
;
2704 memory
->_rlCount
= 0;
2705 memory
->_activities
= activities
;
2706 memory
->_order
= order
;
2707 memory
->_callout
= callout
;
2709 if (context
->retain
) {
2710 memory
->_context
.info
= (void *)context
->retain(context
->info
);
2712 memory
->_context
.info
= context
->info
;
2714 memory
->_context
.retain
= context
->retain
;
2715 memory
->_context
.release
= context
->release
;
2716 memory
->_context
.copyDescription
= context
->copyDescription
;
2718 memory
->_context
.info
= 0;
2719 memory
->_context
.retain
= 0;
2720 memory
->_context
.release
= 0;
2721 memory
->_context
.copyDescription
= 0;
2726 CFOptionFlags
CFRunLoopObserverGetActivities(CFRunLoopObserverRef rlo
) {
2728 __CFGenericValidateType(rlo
, __kCFRunLoopObserverTypeID
);
2729 return rlo
->_activities
;
2732 CFIndex
CFRunLoopObserverGetOrder(CFRunLoopObserverRef rlo
) {
2734 __CFGenericValidateType(rlo
, __kCFRunLoopObserverTypeID
);
2738 Boolean
CFRunLoopObserverDoesRepeat(CFRunLoopObserverRef rlo
) {
2740 __CFGenericValidateType(rlo
, __kCFRunLoopObserverTypeID
);
2741 return __CFRunLoopObserverRepeats(rlo
);
2744 void CFRunLoopObserverInvalidate(CFRunLoopObserverRef rlo
) { /* DOES CALLOUT */
2746 __CFGenericValidateType(rlo
, __kCFRunLoopObserverTypeID
);
2748 __CFRunLoopObserverLock(rlo
);
2749 if (__CFIsValid(rlo
)) {
2750 CFRunLoopRef rl
= rlo
->_runLoop
;
2751 __CFUnsetValid(rlo
);
2752 __CFRunLoopObserverUnlock(rlo
);
2756 array
= CFRunLoopCopyAllModes(rl
);
2757 for (idx
= CFArrayGetCount(array
); idx
--;) {
2758 CFStringRef modeName
= CFArrayGetValueAtIndex(array
, idx
);
2759 CFRunLoopRemoveObserver(rl
, rlo
, modeName
);
2761 CFRunLoopRemoveObserver(rl
, rlo
, kCFRunLoopCommonModes
);
2764 if (rlo
->_context
.release
)
2765 rlo
->_context
.release(rlo
->_context
.info
); /* CALLOUT */
2766 rlo
->_context
.info
= NULL
;
2768 __CFRunLoopObserverUnlock(rlo
);
2773 Boolean
CFRunLoopObserverIsValid(CFRunLoopObserverRef rlo
) {
2775 return __CFIsValid(rlo
);
2778 void CFRunLoopObserverGetContext(CFRunLoopObserverRef rlo
, CFRunLoopObserverContext
*context
) {
2780 __CFGenericValidateType(rlo
, __kCFRunLoopObserverTypeID
);
2781 CFAssert1(0 == context
->version
, __kCFLogAssertion
, "%s(): context version not initialized to 0", __PRETTY_FUNCTION__
);
2782 *context
= rlo
->_context
;
2785 /* CFRunLoopTimer */
2787 static CFStringRef
__CFRunLoopTimerCopyDescription(CFTypeRef cf
) { /* DOES CALLOUT */
2788 CFRunLoopTimerRef rlt
= (CFRunLoopTimerRef
)cf
;
2790 CFStringRef contextDesc
= NULL
;
2792 __CFRunLoopTimerFireTSRLock();
2793 fireTime
= rlt
->_fireTSR
;
2794 __CFRunLoopTimerFireTSRUnlock();
2795 if (NULL
!= rlt
->_context
.copyDescription
) {
2796 contextDesc
= rlt
->_context
.copyDescription(rlt
->_context
.info
);
2798 if (NULL
== contextDesc
) {
2799 contextDesc
= CFStringCreateWithFormat(CFGetAllocator(rlt
), NULL
, CFSTR("<CFRunLoopTimer context %p>"), rlt
->_context
.info
);
2801 int64_t now2
= (int64_t)mach_absolute_time();
2802 CFAbsoluteTime now1
= CFAbsoluteTimeGetCurrent();
2803 #if DEPLOYMENT_TARGET_MACOSX
2804 void *addr
= rlt
->_callout
;
2806 const char *name
= (dladdr(addr
, &info
) && info
.dli_saddr
== addr
&& info
.dli_sname
) ? info
.dli_sname
: "???";
2807 result
= CFStringCreateWithFormat(CFGetAllocator(rlt
), NULL
, CFSTR("<CFRunLoopTimer %p [%p]>{locked = %s, valid = %s, interval = %0.09g, next fire date = %0.09g, order = %d, callout = %s (%p), context = %@}"), cf
, CFGetAllocator(rlt
), lockCount(rlt
->_lock
) ? "Yes" : "No", __CFIsValid(rlt
) ? "Yes" : "No", __CFTSRToTimeInterval(rlt
->_intervalTSR
), now1
+ __CFTSRToTimeInterval(fireTime
- now2
), rlt
->_order
, name
, addr
, contextDesc
);
2809 #error Unknown or unspecified DEPLOYMENT_TARGET
2811 CFRelease(contextDesc
);
2815 static void __CFRunLoopTimerDeallocate(CFTypeRef cf
) { /* DOES CALLOUT */
2816 CFRunLoopTimerRef rlt
= (CFRunLoopTimerRef
)cf
;
2817 CFRunLoopTimerInvalidate(rlt
); /* DOES CALLOUT */
2820 static const CFRuntimeClass __CFRunLoopTimerClass
= {
2825 __CFRunLoopTimerDeallocate
,
2829 __CFRunLoopTimerCopyDescription
2832 __private_extern__
void __CFRunLoopTimerInitialize(void) {
2833 __kCFRunLoopTimerTypeID
= _CFRuntimeRegisterClass(&__CFRunLoopTimerClass
);
2836 CFTypeID
CFRunLoopTimerGetTypeID(void) {
2837 return __kCFRunLoopTimerTypeID
;
2840 CFRunLoopTimerRef
CFRunLoopTimerCreate(CFAllocatorRef allocator
, CFAbsoluteTime fireDate
, CFTimeInterval interval
, CFOptionFlags flags
, CFIndex order
, CFRunLoopTimerCallBack callout
, CFRunLoopTimerContext
*context
) {
2842 CFRunLoopTimerRef memory
;
2844 size
= sizeof(struct __CFRunLoopTimer
) - sizeof(CFRuntimeBase
);
2845 memory
= (CFRunLoopTimerRef
)_CFRuntimeCreateInstance(allocator
, __kCFRunLoopTimerTypeID
, size
, NULL
);
2846 if (NULL
== memory
) {
2849 __CFSetValid(memory
);
2850 __CFRunLoopTimerUnsetFiring(memory
);
2851 __CFRunLoopTimerUnsetDidFire(memory
);
2852 CF_SPINLOCK_INIT_FOR_STRUCTS(memory
->_lock
);
2853 memory
->_runLoop
= NULL
;
2854 memory
->_rlCount
= 0;
2855 #if DEPLOYMENT_TARGET_MACOSX
2856 memory
->_port
= MACH_PORT_NULL
;
2858 memory
->_order
= order
;
2859 int64_t now2
= (int64_t)mach_absolute_time();
2860 CFAbsoluteTime now1
= CFAbsoluteTimeGetCurrent();
2861 if (3.1556952e+9 < fireDate
) fireDate
= 3.1556952e+9;
2862 if (fireDate
< now1
) {
2863 memory
->_fireTSR
= now2
;
2864 } else if (now1
+ __CFTSRToTimeInterval(LLONG_MAX
) < fireDate
) {
2865 memory
->_fireTSR
= LLONG_MAX
;
2867 memory
->_fireTSR
= now2
+ __CFTimeIntervalToTSR(fireDate
- now1
);
2869 if (3.1556952e+9 < interval
) interval
= 3.1556952e+9;
2870 if (interval
<= 0.0) {
2871 memory
->_intervalTSR
= 0;
2872 } else if (__CFTSRToTimeInterval(LLONG_MAX
) < interval
) {
2873 memory
->_intervalTSR
= LLONG_MAX
;
2875 memory
->_intervalTSR
= __CFTimeIntervalToTSR(interval
);
2877 memory
->_callout
= callout
;
2878 if (NULL
!= context
) {
2879 if (context
->retain
) {
2880 memory
->_context
.info
= (void *)context
->retain(context
->info
);
2882 memory
->_context
.info
= context
->info
;
2884 memory
->_context
.retain
= context
->retain
;
2885 memory
->_context
.release
= context
->release
;
2886 memory
->_context
.copyDescription
= context
->copyDescription
;
2888 memory
->_context
.info
= 0;
2889 memory
->_context
.retain
= 0;
2890 memory
->_context
.release
= 0;
2891 memory
->_context
.copyDescription
= 0;
2896 CFAbsoluteTime
CFRunLoopTimerGetNextFireDate(CFRunLoopTimerRef rlt
) {
2898 int64_t fireTime
, result
= 0;
2899 CF_OBJC_FUNCDISPATCH0(__kCFRunLoopTimerTypeID
, CFAbsoluteTime
, rlt
, "_cffireTime");
2900 __CFGenericValidateType(rlt
, __kCFRunLoopTimerTypeID
);
2901 __CFRunLoopTimerFireTSRLock();
2902 fireTime
= rlt
->_fireTSR
;
2903 __CFRunLoopTimerFireTSRUnlock();
2904 __CFRunLoopTimerLock(rlt
);
2905 if (__CFIsValid(rlt
)) {
2908 __CFRunLoopTimerUnlock(rlt
);
2909 int64_t now2
= (int64_t)mach_absolute_time();
2910 CFAbsoluteTime now1
= CFAbsoluteTimeGetCurrent();
2911 return (0 == result
) ? 0.0 : now1
+ __CFTSRToTimeInterval(result
- now2
);
2914 void CFRunLoopTimerSetNextFireDate(CFRunLoopTimerRef rlt
, CFAbsoluteTime fireDate
) {
2916 __CFRunLoopTimerFireTSRLock();
2917 int64_t now2
= (int64_t)mach_absolute_time();
2918 CFAbsoluteTime now1
= CFAbsoluteTimeGetCurrent();
2919 if (3.1556952e+9 < fireDate
) fireDate
= 3.1556952e+9;
2920 if (fireDate
< now1
) {
2921 rlt
->_fireTSR
= now2
;
2922 } else if (now1
+ __CFTSRToTimeInterval(LLONG_MAX
) < fireDate
) {
2923 rlt
->_fireTSR
= LLONG_MAX
;
2925 rlt
->_fireTSR
= now2
+ __CFTimeIntervalToTSR(fireDate
- now1
);
2927 if (rlt
->_runLoop
!= NULL
) {
2928 __CFRunLoopTimerRescheduleWithAllModes(rlt
, rlt
->_runLoop
);
2930 __CFRunLoopTimerFireTSRUnlock();
2933 CFTimeInterval
CFRunLoopTimerGetInterval(CFRunLoopTimerRef rlt
) {
2935 CF_OBJC_FUNCDISPATCH0(__kCFRunLoopTimerTypeID
, CFTimeInterval
, rlt
, "timeInterval");
2936 __CFGenericValidateType(rlt
, __kCFRunLoopTimerTypeID
);
2937 return __CFTSRToTimeInterval(rlt
->_intervalTSR
);
2940 Boolean
CFRunLoopTimerDoesRepeat(CFRunLoopTimerRef rlt
) {
2942 __CFGenericValidateType(rlt
, __kCFRunLoopTimerTypeID
);
2943 return (0 != rlt
->_intervalTSR
);
2946 CFIndex
CFRunLoopTimerGetOrder(CFRunLoopTimerRef rlt
) {
2948 CF_OBJC_FUNCDISPATCH0(__kCFRunLoopTimerTypeID
, CFIndex
, rlt
, "order");
2949 __CFGenericValidateType(rlt
, __kCFRunLoopTimerTypeID
);
2953 void CFRunLoopTimerInvalidate(CFRunLoopTimerRef rlt
) { /* DOES CALLOUT */
2955 CF_OBJC_FUNCDISPATCH0(__kCFRunLoopTimerTypeID
, void, rlt
, "invalidate");
2956 __CFGenericValidateType(rlt
, __kCFRunLoopTimerTypeID
);
2958 __CFRunLoopTimerLock(rlt
);
2959 if (__CFIsValid(rlt
)) {
2960 CFRunLoopRef rl
= rlt
->_runLoop
;
2961 void *info
= rlt
->_context
.info
;
2962 __CFUnsetValid(rlt
);
2963 #if DEPLOYMENT_TARGET_MACOSX
2964 __CFRunLoopTimerPortMapLock();
2965 if (NULL
!= __CFRLTPortMap
) {
2966 CFDictionaryRemoveValue(__CFRLTPortMap
, (void *)(uintptr_t)rlt
->_port
);
2968 __CFRunLoopTimerPortMapUnlock();
2969 mk_timer_destroy(rlt
->_port
);
2970 rlt
->_port
= MACH_PORT_NULL
;
2972 rlt
->_context
.info
= NULL
;
2973 __CFRunLoopTimerUnlock(rlt
);
2977 array
= CFRunLoopCopyAllModes(rl
);
2978 for (idx
= CFArrayGetCount(array
); idx
--;) {
2979 CFStringRef modeName
= CFArrayGetValueAtIndex(array
, idx
);
2980 CFRunLoopRemoveTimer(rl
, rlt
, modeName
);
2982 CFRunLoopRemoveTimer(rl
, rlt
, kCFRunLoopCommonModes
);
2985 if (NULL
!= rlt
->_context
.release
) {
2986 rlt
->_context
.release(info
); /* CALLOUT */
2989 __CFRunLoopTimerUnlock(rlt
);
2994 Boolean
CFRunLoopTimerIsValid(CFRunLoopTimerRef rlt
) {
2996 CF_OBJC_FUNCDISPATCH0(__kCFRunLoopTimerTypeID
, Boolean
, rlt
, "isValid");
2997 __CFGenericValidateType(rlt
, __kCFRunLoopTimerTypeID
);
2998 return __CFIsValid(rlt
);
3001 void CFRunLoopTimerGetContext(CFRunLoopTimerRef rlt
, CFRunLoopTimerContext
*context
) {
3003 __CFGenericValidateType(rlt
, __kCFRunLoopTimerTypeID
);
3004 CFAssert1(0 == context
->version
, __kCFLogAssertion
, "%s(): context version not initialized to 0", __PRETTY_FUNCTION__
);
3005 *context
= rlt
->_context
;