Author: mlytwyn Date: Tue Sep 20 20:15:04 2016 New Revision: 40093 URL: http://svn.gna.org/viewcvs/gnustep?rev=40093&view=rev Log: Revert GSRunLoopCtxt.h and NSRunLoop.m trnk merges due to hangups
Modified: libs/base/branches/gnustep_testplant_branch/Source/GSRunLoopCtxt.h libs/base/branches/gnustep_testplant_branch/Source/NSRunLoop.m Modified: libs/base/branches/gnustep_testplant_branch/Source/GSRunLoopCtxt.h URL: http://svn.gna.org/viewcvs/gnustep/libs/base/branches/gnustep_testplant_branch/Source/GSRunLoopCtxt.h?rev=40093&r1=40092&r2=40093&view=diff ============================================================================== --- libs/base/branches/gnustep_testplant_branch/Source/GSRunLoopCtxt.h (original) +++ libs/base/branches/gnustep_testplant_branch/Source/GSRunLoopCtxt.h Tue Sep 20 20:15:04 2016 @@ -36,8 +36,13 @@ #define GSI_ARRAY_TYPES GSUNION_OBJ +#if GS_WITH_GC == 0 #define GSI_ARRAY_RELEASE(A, X) [(X).obj release] #define GSI_ARRAY_RETAIN(A, X) [(X).obj retain] +#else +#define GSI_ARRAY_RELEASE(A, X) +#define GSI_ARRAY_RETAIN(A, X) +#endif #include "GNUstepBase/GSIArray.h" @@ -62,8 +67,9 @@ unsigned maxTimers; GSIArray watchers; /** The inputs set for the runloop mode */ unsigned maxWatchers; + NSTimer *housekeeper; /** Housekeeping timer for loop. */ @private -#if defined(_WIN32) +#if defined(__MINGW__) NSMapTable *handleMap; NSMapTable *winMsgMap; #else @@ -82,7 +88,7 @@ } /* Check to see of the thread has been awakened, blocking until it * does get awakened or until the limit date has been reached. - * A date in the past (or nil) results in a check followed by an + * A date in the past (or nil) results in a check follwed by an * immediate return. */ + (BOOL) awakenedBefore: (NSDate*)when; Modified: libs/base/branches/gnustep_testplant_branch/Source/NSRunLoop.m URL: http://svn.gna.org/viewcvs/gnustep/libs/base/branches/gnustep_testplant_branch/Source/NSRunLoop.m?rev=40093&r1=40092&r2=40093&view=diff ============================================================================== --- libs/base/branches/gnustep_testplant_branch/Source/NSRunLoop.m (original) +++ libs/base/branches/gnustep_testplant_branch/Source/NSRunLoop.m Tue Sep 20 20:15:04 2016 @@ -62,15 +62,6 @@ #include <math.h> #include <time.h> -#if HAVE_DISPATCH_GET_MAIN_QUEUE_HANDLE_NP && HAVE_DISPATCH_MAIN_QUEUE_DRAIN_NP -# define RL_INTEGRATE_DISPATCH 1 -# ifdef HAVE_DISPATCH_H -# include <dispatch.h> -# elif HAVE_DISPATCH_DISPATCH_H -# include <dispatch/dispatch.h> -# endif -#endif - NSString * const NSDefaultRunLoopMode = @"NSDefaultRunLoopMode"; @@ -249,8 +240,13 @@ #ifndef GSI_ARRAY_TYPES #define GSI_ARRAY_TYPES GSUNION_OBJ +#if GS_WITH_GC == 0 #define GSI_ARRAY_RELEASE(A, X) [(X).obj release] #define GSI_ARRAY_RETAIN(A, X) [(X).obj retain] +#else +#define GSI_ARRAY_RELEASE(A, X) +#define GSI_ARRAY_RETAIN(A, X) +#endif #include "GNUstepBase/GSIArray.h" #endif @@ -390,26 +386,7 @@ @end -#ifdef RL_INTEGRATE_DISPATCH -@interface GSMainQueueDrainer : NSObject <RunLoopEvents> -+ (void*) mainQueueFileDescriptor; -@end -@implementation GSMainQueueDrainer -+ (void*) mainQueueFileDescriptor -{ - return (void*)(uintptr_t)dispatch_get_main_queue_handle_np(); -} - -- (void) receivedEvent: (void*)data - type: (RunLoopEventType)type - extra: (void*)extra - forMode: (NSString*)mode -{ - dispatch_main_queue_drain_np(); -} -@end -#endif @interface NSRunLoop (Private) @@ -577,8 +554,12 @@ NSObjectMapValueCallBacks, 0); _timedPerformers = [[NSMutableArray alloc] initWithCapacity: 8]; #ifdef HAVE_POLL_F +#if GS_WITH_GC + _extra = NSAllocateCollectable(sizeof(pollextra), NSScannedOption); +#else _extra = NSZoneMalloc(NSDefaultMallocZone(), sizeof(pollextra)); memset(_extra, '\0', sizeof(pollextra)); +#endif #endif } return self; @@ -749,6 +730,7 @@ if (nil != current && [GSCurrentThread() isMainThread] == YES) { NSAutoreleasePool *arp = [NSAutoreleasePool new]; + GSRunLoopCtxt *context; NSNotificationCenter *ctr; NSNotification *not; NSInvocation *inv; @@ -767,25 +749,27 @@ [inv setArgument: ¬ atIndex: 2]; [inv retainArguments]; + context = NSMapGet(current->_contextMap, NSDefaultRunLoopMode); + if (context == nil) + { + context = [GSRunLoopCtxt alloc]; + context = [context initWithMode: NSDefaultRunLoopMode + extra: current->_extra]; + NSMapInsert(current->_contextMap, context->mode, context); + RELEASE(context); + } + if (context->housekeeper != nil) + { + [context->housekeeper invalidate]; + DESTROY(context->housekeeper); + } timer = [[NSTimer alloc] initWithFireDate: nil interval: 30.0 target: inv selector: NULL userInfo: nil repeats: YES]; - [current addTimer: timer forMode: NSDefaultRunLoopMode]; - - #ifdef RL_INTEGRATE_DISPATCH - // We leak the queue drainer, because it's integral part of RL - // operations - GSMainQueueDrainer *drain = - [NSObject leak: [[GSMainQueueDrainer new] autorelease]]; - [current addEvent: [GSMainQueueDrainer mainQueueFileDescriptor] - type: ET_RDESC - watcher: drain - forMode: NSDefaultRunLoopMode]; - - #endif + context->housekeeper = timer; [arp drain]; } } @@ -964,10 +948,28 @@ return YES; } -- (NSDate*) _limitDateForContext: (GSRunLoopCtxt *)context -{ +/** + * Fires timers whose fire date has passed, and checks timers and limit dates + * for input sources, determining the earliest time that any future timeout + * becomes due. Returns that date/time.<br /> + * Returns distant future if the loop contains no timers, just input sources + * without timeouts.<br /> + * Returns nil if the loop contains neither timers nor input sources. + */ +- (NSDate*) limitDateForMode: (NSString*)mode +{ + GSRunLoopCtxt *context; NSDate *when = nil; + + context = NSMapGet(_contextMap, mode); + if (context != nil) + { + NSString *savedMode = _currentMode; NSAutoreleasePool *arp = [NSAutoreleasePool new]; + + _currentMode = mode; + NS_DURING + { GSIArray timers = context->timers; NSTimeInterval now; NSDate *earliest; @@ -990,6 +992,23 @@ * this method. */ now = GSPrivateTimeNow(); + + /* Fire housekeeping timer as necessary + */ + if ((t = context->housekeeper) != nil) + { + if (timerInvalidated(t)) + { + DESTROY(context->housekeeper); + } + else if ([(d=timerDate(t)) timeIntervalSinceReferenceDate] <= now) + { + [t fire]; + GSPrivateNotifyASAP(_currentMode); + IF_NO_GC([arp emptyPool];) + updateTimer(t, d, now); + } + } /* Fire the oldest/first valid timer whose fire date has passed * and fire it. @@ -1062,11 +1081,21 @@ */ if (earliest != nil) { - [arp drain]; - when = AUTORELEASE([earliest copy]); + when = [earliest copy]; } - else - { + _currentMode = savedMode; + } + NS_HANDLER + { + _currentMode = savedMode; + [localException raise]; + } + NS_ENDHANDLER + + [arp release]; + + if (when == nil) + { GSIArray watchers = context->watchers; unsigned i = GSIArrayCount(watchers); @@ -1083,42 +1112,13 @@ { when = theFuture; } - [arp drain]; - } - - return when; -} - -/** - * Fires timers whose fire date has passed, and checks timers and limit dates - * for input sources, determining the earliest time that any future timeout - * becomes due. Returns that date/time.<br /> - * Returns distant future if the loop contains no timers, just input sources - * without timeouts.<br /> - * Returns nil if the loop contains neither timers nor input sources. - */ -- (NSDate*) limitDateForMode: (NSString*)mode - { - GSRunLoopCtxt *context; - NSDate *when = nil; - - context = NSMapGet(_contextMap, mode); - if (context != nil) - { - NSString *savedMode = _currentMode; - - _currentMode = mode; - NS_DURING - { - when = [self _limitDateForContext: context]; - _currentMode = savedMode; - } - NS_HANDLER - { - _currentMode = savedMode; - [localException raise]; - } - NS_ENDHANDLER + } +#if !GS_WITH_GC + else + { + AUTORELEASE(when); + } +#endif NSDebugMLLog(@"NSRunLoop", @"limit date %f in %@", nil == when ? 0.0 : [when timeIntervalSinceReferenceDate], mode); @@ -1129,9 +1129,9 @@ /** * Listen for events from input sources.<br /> * If limit_date is nil or in the past, then don't wait; - * just fire timers, poll inputs and return, otherwise block - * (firing timers when they are due) until input is available - * or until the earliest limit date has passed (whichever comes first).<br /> + * just poll inputs and return, + * otherwise block until input is available or until the + * earliest limit date has passed (whichever comes first).<br /> * If the supplied mode is nil, uses NSDefaultRunLoopMode.<br /> * If there are no input sources or timers in the mode, returns immediately. */ @@ -1149,27 +1149,30 @@ { mode = NSDefaultRunLoopMode; } + _currentMode = mode; context = NSMapGet(_contextMap, mode); - if (nil == context) - { - return; - } - _currentMode = mode; [self _checkPerformers: context]; NS_DURING { - BOOL done = NO; - NSDate *when; - - while (NO == done) - { - when = [self _limitDateForContext: context]; - if (nil == when) - { - NSDebugMLLog(@"NSRunLoop", - @"no inputs or timers in mode %@", mode); + /* + * If we have a housekeeping timer, and it is earlier than the + * limit date we have been given, we use the date of the housekeeper + * to determine when to stop. + */ + if (limit_date != nil && context != nil && context->housekeeper != nil + && [timerDate(context->housekeeper) timeIntervalSinceReferenceDate] + < [limit_date timeIntervalSinceReferenceDate]) + { + limit_date = timerDate(context->housekeeper); + } + + if (context == nil + || (GSIArrayCount(context->watchers) == 0 + && GSIArrayCount(context->timers) == 0)) + { + NSDebugMLLog(@"NSRunLoop", @"no inputs or timers in mode %@", mode); GSPrivateNotifyASAP(_currentMode); GSPrivateNotifyIdle(_currentMode); /* Pause until the limit date or until we might have @@ -1177,27 +1180,19 @@ */ [GSRunLoopCtxt awakenedBefore: nil]; GSPrivateCheckTasks(); + if (context != nil) + { [self _checkPerformers: context]; + } GSPrivateNotifyASAP(_currentMode); - [_contextStack removeObjectIdenticalTo: context]; _currentMode = savedMode; [arp drain]; NS_VOIDRETURN; } - else - { - if (nil == limit_date) - { - when = nil; - } - else - { - when = [when earlierDate: limit_date]; - } - } /* Find out how much time we should wait, and set SELECT_TIMEOUT. */ - if (nil == when || (ti = [when timeIntervalSinceNow]) <= 0.0) + if (limit_date == nil + || (ti = [limit_date timeIntervalSinceNow]) <= 0.0) { /* Don't wait at all. */ timeout_ms = 0; @@ -1223,30 +1218,23 @@ { [_contextStack addObject: context]; } - done = [context pollUntil: timeout_ms within: _contextStack]; - if (NO == done) + if ([context pollUntil: timeout_ms within: _contextStack] == NO) { GSPrivateNotifyIdle(_currentMode); - if (nil == limit_date || [limit_date timeIntervalSinceNow] <= 0.0) - { - done = YES; - } - } + } [self _checkPerformers: context]; GSPrivateNotifyASAP(_currentMode); - [context endPoll]; + _currentMode = savedMode; /* Once a poll has been completed on a context, we can remove that - * context from the stack even if it is actually polling at an outer + * context from the stack even if it actually polling at an outer * level of re-entrancy ... since the poll we have just done will * have handled any events that the outer levels would have wanted - * to handle, and the polling for this context will be marked as - * ended. + * to handle, and the polling for this context will be marked as ended. */ + [context endPoll]; [_contextStack removeObjectIdenticalTo: context]; - } - - _currentMode = savedMode; + NSDebugMLLog(@"NSRunLoop", @"accept I/P completed in %@", mode); } NS_HANDLER { @@ -1256,10 +1244,21 @@ [localException raise]; } NS_ENDHANDLER - NSDebugMLLog(@"NSRunLoop", @"accept I/P completed in %@", mode); [arp drain]; } +/** + * Calls -limitDateForMode: to determine if a timeout occurs before the + * specified date, then calls -acceptInputForMode:beforeDate: to run the + * loop once.<br /> + * The specified date may be nil ... in which case the loop runs + * until the limit date of the first input or timeout.<br /> + * If the specified date is in the past, this runs the loop once only, + * to handle any events already available.<br /> + * If there are no input sources or timers in mode, this method + * returns NO without running the loop (irrespective of the supplied + * date argument), otherwise returns YES. + */ - (BOOL) runMode: (NSString*)mode beforeDate: (NSDate*)date { NSAutoreleasePool *arp = [NSAutoreleasePool new]; @@ -1283,31 +1282,28 @@ _currentMode = savedMode; /* Find out how long we can wait before first limit date. - * If there are no input sources or timers, return immediately. */ d = [self limitDateForMode: mode]; - if (nil == d) + if (d == nil) { [arp drain]; return NO; } - /* Use the earlier of the two dates we have (nil date is like distant past). + /* Use the earlier of the two dates we have. + * Retain the date in case the firing of a timer (or some other event) + * releases it. */ - if (nil == date) - { - [self acceptInputForMode: mode beforeDate: nil]; - } - else - { - /* Retain the date in case the firing of a timer (or some other event) - * releases it. - */ - d = [[d earlierDate: date] copy]; + if (date != nil) + { + d = [d earlierDate: date]; + } + [d retain]; + + /* Wait, listening to our input sources. */ [self acceptInputForMode: mode beforeDate: d]; - [d release]; - } - + + [d release]; [arp drain]; return YES; } @@ -1329,17 +1325,16 @@ */ - (void) runUntilDate: (NSDate*)date { + double ti = [date timeIntervalSinceNow]; BOOL mayDoMore = YES; /* Positive values are in the future. */ - while (YES == mayDoMore) - { + while (ti > 0 && mayDoMore == YES) + { + NSDebugMLLog(@"NSRunLoop", @"run until date %f seconds from now", ti); mayDoMore = [self runMode: NSDefaultRunLoopMode beforeDate: date]; - if (nil == date || [date timeIntervalSinceNow] <= 0.0) - { - mayDoMore = NO; - } -} + ti = [date timeIntervalSinceNow]; + } } @end @@ -1547,3 +1542,4 @@ } @end + _______________________________________________ Gnustep-cvs mailing list Gnustep-cvs@gna.org https://mail.gna.org/listinfo/gnustep-cvs