mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-30 16:30:41 +00:00
use fairStart to get a fairer distribution of I/O across multiple handles
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@40045 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
6f890a5095
commit
945ca4abfb
1 changed files with 120 additions and 94 deletions
|
@ -382,23 +382,32 @@ static const NSMapTableValueCallBacks WatcherMapValueCallBacks =
|
|||
wait_timeout = 0;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
handleArray[i++] = threadInfo->event; // Signal from other thread
|
||||
hEnum = NSEnumerateMapTable(handleMap);
|
||||
while (NSNextMapEnumeratorPair(&hEnum, &handle, (void**)&watcher))
|
||||
handleArray[0] = threadInfo->event; // Signal from other thread
|
||||
num_handles = NSCountMapTable(handleMap) + 1;
|
||||
if (num_handles >= MAXIMUM_WAIT_OBJECTS)
|
||||
{
|
||||
if (i < MAXIMUM_WAIT_OBJECTS-1)
|
||||
NSLog(@"Too many handles to wait for ... only using %d of %d",
|
||||
MAXIMUM_WAIT_OBJECTS-1, num_handles);
|
||||
num_handles = MAXIMUM_WAIT_OBJECTS-1;
|
||||
}
|
||||
count = num_handles - 1; // Count of handles excluding thread event
|
||||
if (count > 0)
|
||||
{
|
||||
i = 1 + (fairStart++ % count);
|
||||
hEnum = NSEnumerateMapTable(handleMap);
|
||||
while (count-- > 0
|
||||
&& NSNextMapEnumeratorPair(&hEnum, &handle, (void**)&watcher))
|
||||
{
|
||||
if (i >= num_handles)
|
||||
{
|
||||
i = 1;
|
||||
}
|
||||
handleArray[i++] = (HANDLE)handle;
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"Too many handles to wait for ... only using %d of %d",
|
||||
i, num_handles);
|
||||
}
|
||||
NSEndMapTableEnumeration(&hEnum);
|
||||
}
|
||||
NSEndMapTableEnumeration(&hEnum);
|
||||
num_handles = i;
|
||||
|
||||
completed = NO;
|
||||
|
||||
/* Clear all the windows messages first before we wait,
|
||||
* since MsgWaitForMultipleObjects only signals on NEW messages
|
||||
|
@ -406,11 +415,17 @@ static const NSMapTableValueCallBacks WatcherMapValueCallBacks =
|
|||
if ([self processAllWindowsMessages: num_winMsgs within: contexts] == YES)
|
||||
{
|
||||
// Processed something ... no need to wait.
|
||||
wait_return = WAIT_OBJECT_0;
|
||||
wait_timeout = 0;
|
||||
num_winMsgs = 0;
|
||||
existingMessages = YES;
|
||||
}
|
||||
else if (num_winMsgs > 0)
|
||||
|
||||
if (num_winMsgs > 0)
|
||||
{
|
||||
NSDebugMLLog(@"NSRunLoop",
|
||||
@"wait for messages and %d handles for %d milliseconds",
|
||||
num_handles, wait_timeout);
|
||||
|
||||
/*
|
||||
* Wait for signalled events or window messages.
|
||||
*/
|
||||
|
@ -419,6 +434,9 @@ static const NSMapTableValueCallBacks WatcherMapValueCallBacks =
|
|||
}
|
||||
else if (num_handles > 0)
|
||||
{
|
||||
NSDebugMLLog(@"NSRunLoop",
|
||||
@"wait for %d handles for %d milliseconds", num_handles, wait_timeout);
|
||||
|
||||
/*
|
||||
* We are not interested in windows messages ... just wait for
|
||||
* signalled events.
|
||||
|
@ -428,19 +446,22 @@ static const NSMapTableValueCallBacks WatcherMapValueCallBacks =
|
|||
}
|
||||
else
|
||||
{
|
||||
NSDebugMLLog(@"NSRunLoop",
|
||||
@"wait for %d milliseconds", wait_timeout);
|
||||
SleepEx(wait_timeout, TRUE);
|
||||
wait_return = WAIT_OBJECT_0;
|
||||
wait_return = WAIT_TIMEOUT;
|
||||
}
|
||||
NSDebugMLLog(@"NSRunLoop", @"wait returned %d", wait_return);
|
||||
|
||||
// check wait errors
|
||||
if (wait_return == WAIT_FAILED)
|
||||
if (WAIT_FAILED == wait_return
|
||||
|| (wait_return >= WAIT_ABANDONED_0
|
||||
&& wait_return < WAIT_ABANDONED_0 + num_handles))
|
||||
{
|
||||
int i;
|
||||
BOOL found = NO;
|
||||
|
||||
NSDebugMLLog(@"NSRunLoop", @"WaitForMultipleObjects() error in "
|
||||
@"-acceptInputForMode:beforeDate: %@", [NSError _last]);
|
||||
@"-pollUntil:within: %@", [NSError _last]);
|
||||
/*
|
||||
* Check each handle in turn until either we find one which has an
|
||||
* event signalled, or we find the one which caused the original
|
||||
|
@ -461,7 +482,7 @@ static const NSMapTableValueCallBacks WatcherMapValueCallBacks =
|
|||
if (found == NO)
|
||||
{
|
||||
NSLog(@"WaitForMultipleObjects() error in "
|
||||
@"-acceptInputForMode:beforeDate: %@", [NSError _last]);
|
||||
@"-pollUntil:within: %@", [NSError _last]);
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
@ -476,98 +497,103 @@ static const NSMapTableValueCallBacks WatcherMapValueCallBacks =
|
|||
GSRunLoopWatcher *watcher;
|
||||
|
||||
watcher = (GSRunLoopWatcher*)GSIArrayItemAtIndex(_trigger, count).obj;
|
||||
if (watcher->_invalidated == NO)
|
||||
{
|
||||
NSDebugMLLog(@"NSRunLoop", @"trigger watcher %@", watcher);
|
||||
i = [contexts count];
|
||||
while (i-- > 0)
|
||||
{
|
||||
GSRunLoopCtxt *c = [contexts objectAtIndex: i];
|
||||
if (watcher->_invalidated == NO)
|
||||
{
|
||||
NSDebugMLLog(@"NSRunLoop", @"trigger watcher %@", watcher);
|
||||
i = [contexts count];
|
||||
while (i-- > 0)
|
||||
{
|
||||
GSRunLoopCtxt *c = [contexts objectAtIndex: i];
|
||||
|
||||
if (c != self)
|
||||
{
|
||||
[c endEvent: (void*)watcher for: watcher];
|
||||
}
|
||||
}
|
||||
/*
|
||||
* The watcher is still valid - so call its
|
||||
* receivers event handling method.
|
||||
*/
|
||||
[watcher->receiver receivedEvent: watcher->data
|
||||
type: watcher->type
|
||||
extra: watcher->data
|
||||
forMode: mode];
|
||||
}
|
||||
GSPrivateNotifyASAP(mode);
|
||||
if (c != self)
|
||||
{
|
||||
[c endEvent: (void*)watcher for: watcher];
|
||||
}
|
||||
}
|
||||
/*
|
||||
* The watcher is still valid - so call its
|
||||
* receivers event handling method.
|
||||
*/
|
||||
[watcher->receiver receivedEvent: watcher->data
|
||||
type: watcher->type
|
||||
extra: watcher->data
|
||||
forMode: mode];
|
||||
}
|
||||
GSPrivateNotifyASAP(mode);
|
||||
}
|
||||
|
||||
if (existingMessages)
|
||||
if (WAIT_TIMEOUT == wait_return)
|
||||
{
|
||||
NSDebugMLLog(@"NSRunLoop", @"processed windows messages");
|
||||
return YES;
|
||||
// there is no event to handle
|
||||
if (existingMessages)
|
||||
{
|
||||
NSDebugMLLog(@"NSRunLoop", @"processed windows messages");
|
||||
}
|
||||
else
|
||||
{
|
||||
NSDebugMLLog(@"NSRunLoop", @"timeout without events");
|
||||
completed = YES;
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
// if there are windows message
|
||||
if (wait_return == WAIT_OBJECT_0 + num_handles)
|
||||
else if (WAIT_OBJECT_0 + num_handles == wait_return)
|
||||
{
|
||||
// one or more windows message
|
||||
NSDebugMLLog(@"NSRunLoop", @"processing windows messages");
|
||||
return [self processAllWindowsMessages: num_winMsgs within: contexts];
|
||||
[self processAllWindowsMessages: num_winMsgs within: contexts];
|
||||
}
|
||||
|
||||
// if there aren't events
|
||||
if (wait_return == WAIT_TIMEOUT)
|
||||
else if ((i = wait_return - WAIT_OBJECT_0) >= 0 && i < num_handles)
|
||||
{
|
||||
NSDebugMLLog(@"NSRunLoop", @"timeout without events");
|
||||
completed = YES;
|
||||
return NO;
|
||||
}
|
||||
/* Look the event that WaitForMultipleObjects() says is ready;
|
||||
* get the corresponding fd for that handle event and notify
|
||||
* the corresponding object for the ready fd.
|
||||
*/
|
||||
NSDebugMLLog(@"NSRunLoop", @"Handle signalled %d", i);
|
||||
|
||||
/*
|
||||
* Look the event that WaitForMultipleObjects() says is ready;
|
||||
* get the corresponding fd for that handle event and notify
|
||||
* the corresponding object for the ready fd.
|
||||
*/
|
||||
i = wait_return - WAIT_OBJECT_0;
|
||||
handle = handleArray[i];
|
||||
|
||||
NSDebugMLLog(@"NSRunLoop", @"Event listen %d", i);
|
||||
if (handle == threadInfo->event)
|
||||
{
|
||||
watcher = nil;
|
||||
NSDebugMLLog(@"NSRunLoop", @"Fire perform on thread");
|
||||
[threadInfo fire];
|
||||
}
|
||||
else
|
||||
{
|
||||
watcher = (GSRunLoopWatcher*)NSMapGet(handleMap, (void*)handle);
|
||||
NSDebugMLLog(@"NSRunLoop", @"Fire watcher %@", watcher);
|
||||
}
|
||||
if (watcher != nil && watcher->_invalidated == NO)
|
||||
{
|
||||
i = [contexts count];
|
||||
while (i-- > 0)
|
||||
{
|
||||
GSRunLoopCtxt *c = [contexts objectAtIndex: i];
|
||||
|
||||
handle = handleArray[i];
|
||||
|
||||
if (handle == threadInfo->event)
|
||||
{
|
||||
watcher = nil;
|
||||
NSDebugMLLog(@"NSRunLoop", @"Fire perform on thread");
|
||||
[threadInfo fire];
|
||||
if (c != self)
|
||||
{
|
||||
[c endEvent: (void*)handle for: watcher];
|
||||
}
|
||||
}
|
||||
/*
|
||||
* The watcher is still valid - so call its receivers
|
||||
* event handling method.
|
||||
*/
|
||||
[watcher->receiver receivedEvent: watcher->data
|
||||
type: watcher->type
|
||||
extra: (void*)handle
|
||||
forMode: mode];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
watcher = (GSRunLoopWatcher*)NSMapGet(handleMap, (void*)handle);
|
||||
}
|
||||
if (watcher != nil && watcher->_invalidated == NO)
|
||||
{
|
||||
i = [contexts count];
|
||||
while (i-- > 0)
|
||||
{
|
||||
GSRunLoopCtxt *c = [contexts objectAtIndex: i];
|
||||
|
||||
if (c != self)
|
||||
{
|
||||
[c endEvent: (void*)handle for: watcher];
|
||||
}
|
||||
}
|
||||
/*
|
||||
* The watcher is still valid - so call its receivers
|
||||
* event handling method.
|
||||
*/
|
||||
NSDebugMLLog(@"NSRunLoop", @"Event callback found");
|
||||
[watcher->receiver receivedEvent: watcher->data
|
||||
type: watcher->type
|
||||
extra: (void*)handle
|
||||
forMode: mode];
|
||||
NSDebugMLLog(@"NSRunLoop", @"unexpected result %d", wait_return);
|
||||
GSPrivateNotifyASAP(mode);
|
||||
completed = NO;
|
||||
return NO;
|
||||
}
|
||||
|
||||
GSPrivateNotifyASAP(mode);
|
||||
|
||||
completed = YES;
|
||||
return YES;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue