make housekeeping timer more transparent and remove deprecated code

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@22593 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
rfm 2006-03-04 06:47:56 +00:00
parent 68ecc62aba
commit e1b9889677
9 changed files with 96 additions and 130 deletions

View file

@ -1,3 +1,17 @@
2006-03-04 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSRunLoop.m: Rewrite housekeeping timer.
* Source/GSRunLoopCtxt.h: Remove obsolete message/selector.
* Source/win32/GSRunLoopCtxt.m: Add housekeeping timer.
* Source/win32/NSRunLoopWin32.m: remove unused code.
* Source/win32/GNUmakefile: remove /NSRunLoopWin32.m
* Source/win32/NSStreamWin32.m: minor tidyups
* Source/NSThread.m: Use new internal API for housekeeping timer.
* Headers/Foundation/NSRunLoop.h: Remove deprecated mingw api
Basically, remove deprecated mingw32 specific api, and change
housekeeper to try to make it as invisible as possible in terms of
side effects.
2006-03-03 Richard Frith-Macdonald <rfm@gnu.org> 2006-03-03 Richard Frith-Macdonald <rfm@gnu.org>
* Tools/gdomap.c: Check for HAVE_STDINT_H for safety of include * Tools/gdomap.c: Check for HAVE_STDINT_H for safety of include

View file

@ -201,19 +201,4 @@ typedef enum {
- (void) getFds: (int*)fds count: (int*)count; - (void) getFds: (int*)fds count: (int*)count;
@end @end
#if defined(__MINGW32__)
/**
* Obsolete interface that add method to set target for win32 messages.<br />
*/
@interface NSRunLoop(mingw32)
/** Deprecated ... will be removed
*/
- (void) addMsgTarget: (id)target
withMethod: (SEL)selector
forMode: (NSString*)mode;
/** Deprecated ... will be removed
*/
- (void) removeMsgForMode: (NSString*)mode;
@end
#endif
#endif /*__NSRunLoop_h_GNUSTEP_BASE_INCLUDE */ #endif /*__NSRunLoop_h_GNUSTEP_BASE_INCLUDE */

View file

@ -39,10 +39,7 @@ typedef struct{
GSIArray performers; /** The actions to perform regularly. */ GSIArray performers; /** The actions to perform regularly. */
GSIArray timers; /** The timers set for the runloop mode */ GSIArray timers; /** The timers set for the runloop mode */
GSIArray watchers; /** The inputs set for the runloop mode */ GSIArray watchers; /** The inputs set for the runloop mode */
#if defined(__MINGW32__) NSTimer *housekeeper; /** Housekeeping timer for loop. */
id msgTarget; /** Target to raise a win32 message */
SEL msgSelector; /** method of target */
#endif
@private @private
#if defined(__MINGW32__) #if defined(__MINGW32__)
NSMapTable *handleMap; NSMapTable *handleMap;
@ -67,4 +64,8 @@ typedef struct{
- (BOOL) pollUntil: (int)milliseconds within: (NSArray*)contexts; - (BOOL) pollUntil: (int)milliseconds within: (NSArray*)contexts;
@end @end
@interface NSRunLoop (Housekeeper)
- (void) _setHousekeeper: (NSTimer*)timer;
@end
#endif /* __GSRunLoopCtxt_h_GNUSTEP_BASE_INCLUDE */ #endif /* __GSRunLoopCtxt_h_GNUSTEP_BASE_INCLUDE */

View file

@ -770,15 +770,15 @@ extern IMP wRetImp;
/** /**
* Fires timers whose fire date has passed, and checks timers and limit dates * Fires timers whose fire date has passed, and checks timers and limit dates
* for input sources, determining the earliest time that anything watched for * for input sources, determining the earliest time that any future timeout
* becomes useless. Returns that date/time. * becomes due. Returns that date/time.
*/ */
- (NSDate*) limitDateForMode: (NSString*)mode - (NSDate*) limitDateForMode: (NSString*)mode
{ {
extern NSTimer *GSHousekeeper(void); GSRunLoopCtxt *context;
GSRunLoopCtxt *context = NSMapGet(_contextMap, mode);
NSDate *when = nil; NSDate *when = nil;
context = NSMapGet(_contextMap, mode);
if (context != nil) if (context != nil)
{ {
GSRunLoopWatcher *min_watcher = nil; GSRunLoopWatcher *min_watcher = nil;
@ -791,6 +791,19 @@ extern IMP wRetImp;
GSIArray timers = context->timers; GSIArray timers = context->timers;
GSIArray watchers = context->watchers; GSIArray watchers = context->watchers;
/*
* Fire housekeeping timer as necessary
*/
while (context->housekeeper != nil
&& ([timerDate(context->housekeeper) timeIntervalSinceNow] <= 0.0))
{
[context->housekeeper fire];
}
/*
* Handle normal timers ... remove invalidated timers and fire any
* whose date has passed.
*/
while (GSIArrayCount(timers) != 0) while (GSIArrayCount(timers) != 0)
{ {
NSTimer *min_timer = GSIArrayItemAtIndex(timers, 0).obj; NSTimer *min_timer = GSIArrayItemAtIndex(timers, 0).obj;
@ -806,7 +819,7 @@ extern IMP wRetImp;
{ {
when = [timerDate(min_timer) copy]; when = [timerDate(min_timer) copy];
} }
if ([timerDate(min_timer) timeIntervalSinceNow] > 0) if ([timerDate(min_timer) timeIntervalSinceNow] > 0.0)
{ {
break; break;
} }
@ -826,8 +839,6 @@ extern IMP wRetImp;
GSNotifyASAP(); /* Post notifications. */ GSNotifyASAP(); /* Post notifications. */
} }
/* Is this right? At the moment we invalidate and discard watchers
whose limit-dates have passed. */
while (GSIArrayCount(watchers) != 0) while (GSIArrayCount(watchers) != 0)
{ {
min_watcher = GSIArrayItemAtIndex(watchers, 0).obj; min_watcher = GSIArrayItemAtIndex(watchers, 0).obj;
@ -849,9 +860,9 @@ extern IMP wRetImp;
NSDate *nxt = nil; NSDate *nxt = nil;
/* /*
* If the receiver or its delegate wants to know about * If the receiver or its delegate wants to know about
* timeouts - inform it and give it a chance to set a * timeouts - inform it and give it a chance to set a
* revised limit date. * revised limit date.
*/ */
GSIArrayRemoveItemAtIndexNoRelease(watchers, 0); GSIArrayRemoveItemAtIndexNoRelease(watchers, 0);
obj = min_watcher->receiver; obj = min_watcher->receiver;
@ -895,32 +906,6 @@ extern IMP wRetImp;
min_watcher = nil; min_watcher = nil;
} }
} }
/*
* If there is nothing being watched, and no valid timers
* other than the housekeeper, we set when to nil so
* that the housekeeper timer does not keep the runloop
* active. It's a special case set up in NSThread.m
*/
if (min_watcher == nil && when != nil)
{
unsigned count = GSIArrayCount(timers);
while (count-- > 1)
{
NSTimer *tmp = GSIArrayItemAtIndex(timers, 0).obj;
if (timerInvalidated(tmp) == YES)
{
GSIArrayRemoveItemAtIndex(timers, count);
}
}
if (GSIArrayCount(timers) == 1)
{
DESTROY(when);
}
}
_currentMode = savedMode; _currentMode = savedMode;
} }
NS_HANDLER NS_HANDLER
@ -944,25 +929,18 @@ extern IMP wRetImp;
if (min_watcher != nil if (min_watcher != nil
&& [min_watcher->_date compare: when] == NSOrderedAscending) && [min_watcher->_date compare: when] == NSOrderedAscending)
{ {
RELEASE(when); RELEASE(when);
when = min_watcher->_date; when = min_watcher->_date;
} }
else else
{ {
AUTORELEASE(when); AUTORELEASE(when);
} }
} }
else if (min_watcher != nil) else if (min_watcher != nil)
{ {
when = min_watcher->_date; when = min_watcher->_date;
} }
#if defined(__MINGW32__)
// if there are handler for win32 messages
else if (context->msgTarget != nil)
{
when = theFuture;
}
#endif
else else
{ {
return nil; /* Nothing waiting to be done. */ return nil; /* Nothing waiting to be done. */
@ -1006,14 +984,20 @@ extern IMP wRetImp;
GSIArray watchers; GSIArray watchers;
unsigned i; unsigned i;
/*
* 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 || (watchers = context->watchers) == 0 if ((context == nil || (watchers = context->watchers) == 0
|| (i = GSIArrayCount(watchers)) == 0) || (i = GSIArrayCount(watchers)) == 0))
#if defined(__MINGW32__)
// there are inputs for win32 messages
&& context->msgTarget == 0)
#else
)
#endif
{ {
NSDebugMLLog(@"NSRunLoop", @"no inputs in mode %@", mode); NSDebugMLLog(@"NSRunLoop", @"no inputs in mode %@", mode);
GSNotifyASAP(); GSNotifyASAP();
@ -1276,11 +1260,12 @@ extern IMP wRetImp;
/** /**
* Sets up sending of aSelector to target with argument.<br /> * Sets up sending of aSelector to target with argument.<br />
* The selector is sent before the next runloop iteration (unless * The selector is sent before the next runloop iteration (unless
* cancelled before then).<br /> * cancelled before then) in any of the specified modes.<br />
* The target and argument objects are <em>not</em> retained.<br /> * The target and argument objects are <em>not</em> retained.<br />
* The order value is used to determine the order in which messages * The order value is used to determine the order in which messages
* are sent if multiple messages have been set up. Messages with a lower * are sent if multiple messages have been set up. Messages with a lower
* order value are sent first. * order value are sent first.<br />
* If the modes array is empty, this method has no effect.
*/ */
- (void) performSelector: (SEL)aSelector - (void) performSelector: (SEL)aSelector
target: (id)target target: (id)target
@ -1351,3 +1336,29 @@ extern IMP wRetImp;
} }
@end @end
@implementation NSRunLoop (Housekeeper)
- (void) _setHousekeeper: (NSTimer*)timer
{
GSRunLoopCtxt *context;
context = NSMapGet(_contextMap, NSDefaultRunLoopMode);
if (context == nil)
{
context = [[GSRunLoopCtxt alloc] initWithMode: NSDefaultRunLoopMode
extra: _extra];
NSMapInsert(_contextMap, context->mode, context);
RELEASE(context);
}
if (context->housekeeper != timer)
{
[context->housekeeper invalidate];
DESTROY(context->housekeeper);
}
if (timer != nil)
{
context->housekeeper = RETAIN(timer);
}
}
@end

View file

@ -53,6 +53,7 @@
#include "Foundation/NSConnection.h" #include "Foundation/NSConnection.h"
#include "Foundation/NSInvocation.h" #include "Foundation/NSInvocation.h"
#include "GSRunLoopCtxt.h"
typedef struct { @defs(NSThread) } NSThread_ivars; typedef struct { @defs(NSThread) } NSThread_ivars;
@ -353,10 +354,6 @@ GSCurrentThreadDictionary(void)
* on-disk database. * on-disk database.
*/ */
static NSTimer *housekeeper = nil; static NSTimer *housekeeper = nil;
NSTimer *GSHousekeeper(void)
{
return housekeeper;
}
/** /**
* Returns the runloop for the specified thread (or, if t is nil, * Returns the runloop for the specified thread (or, if t is nil,
@ -406,7 +403,8 @@ GSRunLoopForThread(NSThread *t)
selector: NULL selector: NULL
userInfo: nil userInfo: nil
repeats: YES]; repeats: YES];
[r addTimer: housekeeper forMode: NSDefaultRunLoopMode]; [r _setHousekeeper: housekeeper];
RELEASE(housekeeper);
RELEASE(arp); RELEASE(arp);
} }
} }

View file

@ -35,7 +35,6 @@ win32_OBJC_FILES =\
GSRunLoopWatcher.m \ GSRunLoopWatcher.m \
NSMessagePortWin32.m \ NSMessagePortWin32.m \
NSMessagePortNameServerWin32.m \ NSMessagePortNameServerWin32.m \
NSRunLoopWin32.m \
NSStreamWin32.m \ NSStreamWin32.m \
NSUserDefaultsWin32.m \ NSUserDefaultsWin32.m \

View file

@ -131,19 +131,14 @@ static const NSMapTableValueCallBacks WatcherMapValueCallBacks =
WatcherMapValueCallBacks, 0); WatcherMapValueCallBacks, 0);
winMsgMap = NSCreateMapTable(NSIntMapKeyCallBacks, winMsgMap = NSCreateMapTable(NSIntMapKeyCallBacks,
WatcherMapValueCallBacks, 0); WatcherMapValueCallBacks, 0);
msgTarget = nil;
} }
return self; return self;
} }
/* /*
* If there is no msgTarget || there is a generic watcher (watching hwnd == 0), * If there is a generic watcher (watching hwnd == 0),
* loop through all events, and send them to the correct * loop through all events, and send them to the correct
* watcher (if there are any) and then process the rest right here. * watcher (if there are any) and then process the rest right here.
* else if there is a msgTarget,
* then loop through watchers and process for their
* hwnd's only. Then call msgTarget to clean up the rest of them.
* Return a flag to say whether any messages were handled. * Return a flag to say whether any messages were handled.
*/ */
- (BOOL) processAllWindowsMessages:(int)num_winMsgs within: (NSArray*)contexts - (BOOL) processAllWindowsMessages:(int)num_winMsgs within: (NSArray*)contexts
@ -158,7 +153,7 @@ static const NSMapTableValueCallBacks WatcherMapValueCallBacks =
generic = NSMapGet(winMsgMap,0); generic = NSMapGet(winMsgMap,0);
} }
if (msgTarget == nil || (generic != nil && generic->_invalidated == NO)) if (generic != nil && generic->_invalidated == NO)
{ {
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{ {
@ -242,7 +237,6 @@ static const NSMapTableValueCallBacks WatcherMapValueCallBacks =
NSEndMapTableEnumeration(&hEnum); NSEndMapTableEnumeration(&hEnum);
} }
completed = YES; completed = YES;
[msgTarget performSelector: msgSelector withObject: nil];
} }
return handled; return handled;
} }

View file

@ -1,36 +0,0 @@
#include "config.h"
#include "GNUstepBase/preface.h"
#include "Foundation/NSRunLoop.h"
#include "Foundation/NSDebug.h"
#include "../GSRunLoopCtxt.h"
@implementation NSRunLoop (mingw32)
- (void) addMsgTarget: (id)target
withMethod: (SEL)selector
forMode: (NSString*)mode
{
GSRunLoopCtxt *context;
GSOnceMLog(@"This method is deprecated, use -addEvent:type:watcher:forMode");
context = NSMapGet(_contextMap, mode);
if (context == nil)
{
context = [[GSRunLoopCtxt alloc] initWithMode: mode extra: _extra];
NSMapInsert(_contextMap, context->mode, context);
RELEASE(context);
}
context->msgTarget = target;
context->msgSelector = selector;
}
- (void) removeMsgForMode: (NSString*)mode
{
GSRunLoopCtxt *context;
context = NSMapGet(_contextMap, mode);
if (context == nil)
{
return;
}
context->msgTarget = nil;
}
@end

View file

@ -838,7 +838,7 @@ static void setNonblocking(SOCKET fd)
return [super propertyForKey: key]; return [super propertyForKey: key];
} }
- (void)_dispatch - (void) _dispatch
{ {
BOOL av = [self hasSpaceAvailable]; BOOL av = [self hasSpaceAvailable];
NSStreamEvent myEvent = av ? NSStreamEventHasSpaceAvailable : NSStreamEvent myEvent = av ? NSStreamEventHasSpaceAvailable :
@ -856,7 +856,7 @@ static void setNonblocking(SOCKET fd)
} }
} }
- (void)scheduleInRunLoop: (NSRunLoop *)aRunLoop forMode: (NSString *)mode - (void) scheduleInRunLoop: (NSRunLoop *)aRunLoop forMode: (NSString *)mode
{ {
NSAssert(!_runloop || _runloop == aRunLoop, NSAssert(!_runloop || _runloop == aRunLoop,
@"Attempt to schedule in more than one runloop."); @"Attempt to schedule in more than one runloop.");
@ -873,7 +873,7 @@ static void setNonblocking(SOCKET fd)
} }
} }
- (void)removeFromRunLoop: (NSRunLoop *)aRunLoop forMode: (NSString *)mode - (void) removeFromRunLoop: (NSRunLoop *)aRunLoop forMode: (NSString *)mode
{ {
NSAssert(_runloop == aRunLoop, NSAssert(_runloop == aRunLoop,
@"Attempt to remove unscheduled runloop"); @"Attempt to remove unscheduled runloop");
@ -884,7 +884,7 @@ static void setNonblocking(SOCKET fd)
{ {
[_runloop cancelPerformSelector: @selector(_dispatch) [_runloop cancelPerformSelector: @selector(_dispatch)
target: self target: self
argument: nil]; argument: nil];
} }
if ([_modes count] == 0) if ([_modes count] == 0)
{ {