Small optimisation and cleanup when getting methods to perform in loop.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@27603 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2009-01-15 15:06:04 +00:00
parent d8f2b6b369
commit e2d0694264
5 changed files with 85 additions and 16 deletions

View file

@ -1,3 +1,12 @@
2009-01-15 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSRunLoop.m:
* Source/unix/GSRunLoopCtxt.m:
* Source/GSRunLoopCtxt.h:
* Source/win32/GSRunLoopCtxt.m:
Introduce new method to quickly check for notification of methods
to perform in the current loop.
2009-01-14 Richard Frith-Macdonald <rfm@gnu.org>
* Source\NSGarbageCollector.m: Avoid compiler warning

View file

@ -59,6 +59,12 @@ typedef struct{
struct pollfd *pollfds;
#endif
}
/* 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 follwed by an
* immediate return.
*/
+ (BOOL) awakenedBefore: (NSDate*)when;
- (void) endEvent: (void*)data
for: (GSRunLoopWatcher*)watcher;
- (void) endPoll;

View file

@ -1085,7 +1085,8 @@ static inline BOOL timerInvalidated(NSTimer *t)
* 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.
* If the supplied mode is nil, uses NSDefaultRunLoopMode.<br />
* If there are no input sources in the mode, returns immediately.
*/
- (void) acceptInputForMode: (NSString*)mode
beforeDate: (NSDate*)limit_date
@ -1129,20 +1130,10 @@ static inline BOOL timerInvalidated(NSTimer *t)
NSDebugMLLog(@"NSRunLoop", @"no inputs in mode %@", mode);
GSPrivateNotifyASAP();
GSPrivateNotifyIdle();
/*
* Pause for as long as possible (up to the limit date)
* Call the polling method so we notice thread notifications
* that methods should be performed in this loop.
/* Pause until the limit date or until we might have
* a method to perform in this thread.
*/
ti = [limit_date timeIntervalSinceNow];
if (context == nil)
{
context = [[GSRunLoopCtxt alloc] initWithMode: mode
extra: _extra];
NSMapInsert(_contextMap, context->mode, context);
RELEASE(context);
}
[context pollUntil: (int)(ti * 1000) within: nil];
[GSRunLoopCtxt awakenedBefore: nil];
GSPrivateCheckTasks();
if (context != nil)
{
@ -1233,7 +1224,7 @@ static inline BOOL timerInvalidated(NSTimer *t)
d = [self limitDateForMode: mode];
if (d == nil)
{
NSDebugMLLog(@"NSRunLoop", @"run mode with nothing to don %@", mode);
NSDebugMLLog(@"NSRunLoop", @"run mode with nothing to do %@", mode);
/*
* Notify if any tasks have completed.
*/

View file

@ -626,6 +626,27 @@ static void setPollfd(int fd, int event, GSRunLoopCtxt *ctxt)
return YES;
}
+ (BOOL) awakenedBefore: (NSDate*)when
{
GSRunLoopThreadInfo *threadInfo = GSRunLoopInfoForThread(nil);
NSTimeInterval ti = (when == nil) ? 0.0 : [when timeIntervalSinceNow];
int milliseconds = (ti <= 0.0) ? 0 : (int)(ti*1000);
struct pollfd pollfds;
/* Watch for signals from other threads.
*/
pollfds.fd = threadInfo->inputFd;
pollfds.events = POLLIN;
pollfds.revents = 0;
if (poll(&pollfds, 1, milliseconds) == 1)
{
NSDebugMLLog(@"NSRunLoop", @"Fire perform on thread");
[threadInfo fire];
return YES;
}
return NO;
}
#else
- (BOOL) pollUntil: (int)milliseconds within: (NSArray*)contexts
@ -684,7 +705,7 @@ static void setPollfd(int fd, int event, GSRunLoopCtxt *ctxt)
NSResetMapTable(_wfdMap);
GSIArrayRemoveAllItems(_trigger);
/* Watch for signals from otyher threads.
/* Watch for signals from other threads.
*/
fd = threadInfo->inputFd;
if (fd > fdEnd)
@ -1003,5 +1024,31 @@ static void setPollfd(int fd, int event, GSRunLoopCtxt *ctxt)
return YES;
}
+ (BOOL) awakenedBefore: (NSDate*)when
{
GSRunLoopThreadInfo *threadInfo = GSRunLoopInfoForThread(nil);
NSTimeInterval ti = (when == nil) ? 0.0 : [when timeIntervalSinceNow];
int milliseconds = (ti <= 0.0) ? 0 : (int)(ti*1000);
struct timeval timeout;
fd_set read_fds; // Mask for read-ready fds.
fd_set exception_fds; // Mask for exception fds.
fd_set write_fds; // Mask for write-ready fds.
memset(&exception_fds, '\0', sizeof(exception_fds));
memset(&read_fds, '\0', sizeof(read_fds));
memset(&write_fds, '\0', sizeof(write_fds));
timeout.tv_sec = milliseconds/1000;
timeout.tv_usec = (milliseconds - 1000 * timeout.tv_sec) * 1000;
FD_SET (threadInof->inputFd, &read_fds);
if (select (threadInfo->inputFd, &read_fds, &write_fds,
&exception_fds, &timeout) > 0)
{
NSDebugMLLog(@"NSRunLoop", @"Fire perform on thread");
[threadInfo fire];
return YES;
}
return NO;
}
#endif
@end

View file

@ -563,4 +563,20 @@ static const NSMapTableValueCallBacks WatcherMapValueCallBacks =
return YES;
}
+ (BOOL) awakenedBefore: (NSDate*)when
{
GSRunLoopThreadInfo *threadInfo = GSRunLoopInfoForThread(nil);
NSTimeInterval ti = (when == nil) ? 0.0 : [when timeIntervalSinceNow];
int milliseconds = (ti <= 0.0) ? 0 : (int)(ti*1000);
HANDLE h = threadInfo->event;
if (WaitForMultipleObjects(1, &h, NO, milliseconds) != WAIT_TIMEOUT)
{
NSDebugMLLog(@"NSRunLoop", @"Fire perform on thread");
[threadInfo fire];
return YES;
}
return NO;
}
@end