Changes for NSStream support, especially in mingw32 ... not yet complete.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@22693 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2006-03-21 15:33:05 +00:00
parent 6ec821f364
commit 3d99e46faf
22 changed files with 1561 additions and 1863 deletions

View file

@ -31,7 +31,6 @@ SUBPROJECT_NAME = unix
unix_OBJC_FILES = \
GSRunLoopCtxt.m \
GSRunLoopWatcher.m \
NSStream.m
-include Makefile.preamble

View file

@ -30,10 +30,6 @@
#include <unistd.h>
#endif
@interface NSStream (RunLoop)
- (int) _fileDescriptor;
@end
extern BOOL GSCheckTasks();
#if GS_WITH_GC == 0
@ -86,6 +82,8 @@ static const NSMapTableValueCallBacks WatcherMapValueCallBacks =
{
NSFreeMapTable(_wfdMap);
}
GSIArrayEmpty(_trigger);
NSZoneFree(_trigger->zone, (void*)_trigger);
#ifdef HAVE_POLL_F
if (pollfds != 0)
{
@ -119,14 +117,23 @@ static const NSMapTableValueCallBacks WatcherMapValueCallBacks =
case ET_EDESC:
NSMapRemove(_efdMap, data);
break;
case ET_INSTREAM:
NSMapRemove(_rfdMap, data);
break;
case ET_OUTSTREAM:
NSMapRemove(_wfdMap, data);
case ET_TRIGGER:
{
unsigned i = GSIArrayCount(_trigger);
while (i-- > 0)
{
GSIArrayItem item = GSIArrayItemAtIndex(_trigger, i);
if (item.obj == (id)data)
{
GSIArrayRemoveItemAtIndex(_trigger, i);
}
}
}
break;
default:
NSLog(@"Ending an event of unkown type (%d)", type);
NSLog(@"Ending an event of unexpected type (%d)", type);
break;
}
}
@ -172,6 +179,8 @@ static const NSMapTableValueCallBacks WatcherMapValueCallBacks =
WatcherMapValueCallBacks, 0);
_wfdMap = NSCreateMapTable (NSIntMapKeyCallBacks,
WatcherMapValueCallBacks, 0);
_trigger = NSZoneMalloc(z, sizeof(GSIArray_t));
GSIArrayInitWithZoneAndCapacity(_trigger, z, 8);
}
return self;
}
@ -235,7 +244,9 @@ static void setPollfd(int fd, int event, GSRunLoopCtxt *ctxt)
int fdEnd; /* Number of descriptors being monitored. */
int fdIndex;
int fdFinish;
unsigned count;
unsigned int i;
BOOL immediate = NO;
i = GSIArrayCount(watchers);
@ -246,6 +257,7 @@ static void setPollfd(int fd, int event, GSRunLoopCtxt *ctxt)
NSResetMapTable(_efdMap);
NSResetMapTable(_rfdMap);
NSResetMapTable(_wfdMap);
GSIArrayRemoveAllItems(_trigger);
/*
* Do the pre-listening set-up for the file descriptors of this mode.
@ -268,84 +280,72 @@ static void setPollfd(int fd, int event, GSRunLoopCtxt *ctxt)
while (i-- > 0)
{
GSRunLoopWatcher *info;
int fd;
BOOL trigger;
info = GSIArrayItemAtIndex(watchers, i).obj;
if (info->_invalidated == YES)
{
continue;
GSIArrayRemoveItemAtIndex(watchers, i);
}
switch (info->type)
else if ([info runLoopShouldBlock: &trigger] == NO)
{
case ET_EDESC:
fd = (int)(intptr_t)info->data;
setPollfd(fd, POLLPRI, self);
NSMapInsert(_efdMap, (void*)(intptr_t)fd, info);
break;
if (trigger == YES)
{
immediate = YES;
GSIArrayAddItem(_trigger, (GSIArrayItem)(id)info);
}
}
else
{
int fd;
case ET_RDESC:
fd = (int)(intptr_t)info->data;
setPollfd(fd, POLLIN, self);
NSMapInsert(_rfdMap, (void*)(intptr_t)fd, info);
break;
switch (info->type)
{
case ET_EDESC:
fd = (int)(intptr_t)info->data;
setPollfd(fd, POLLPRI, self);
NSMapInsert(_efdMap, (void*)(intptr_t)fd, info);
break;
case ET_WDESC:
fd = (int)(intptr_t)info->data;
setPollfd(fd, POLLOUT, self);
NSMapInsert(_wfdMap, (void*)(intptr_t)fd, info);
break;
case ET_INSTREAM:
fd = [(NSStream*)info->data _fileDescriptor];
if (fd >= 0)
{
setPollfd(fd, POLLOUT, self);
case ET_RDESC:
fd = (int)(intptr_t)info->data;
setPollfd(fd, POLLIN, self);
NSMapInsert(_rfdMap, (void*)(intptr_t)fd, info);
}
break;
break;
case ET_OUTSTREAM:
fd = [(NSStream*)info->data _fileDescriptor];
if (fd >= 0)
{
case ET_WDESC:
fd = (int)(intptr_t)info->data;
setPollfd(fd, POLLOUT, self);
NSMapInsert(_wfdMap, (void*)(intptr_t)fd, info);
}
break;
break;
case ET_RPORT:
if ([info->receiver isValid] == NO)
{
/*
* We must remove an invalidated port.
*/
info->_invalidated = YES;
GSIArrayRemoveItemAtIndex(watchers, i);
}
else
{
id port = info->receiver;
int port_fd_count = 128; // FIXME
int port_fd_array[port_fd_count];
case ET_TRIGGER:
break;
if ([port respondsToSelector:
@selector(getFds:count:)])
{
[port getFds: port_fd_array
count: &port_fd_count];
}
NSDebugMLLog(@"NSRunLoop",
@"listening to %d port handles\n", port_fd_count);
while (port_fd_count--)
{
fd = port_fd_array[port_fd_count];
setPollfd(fd, POLLIN, self);
NSMapInsert(_rfdMap,
(void*)(intptr_t)port_fd_array[port_fd_count], info);
}
}
break;
case ET_RPORT:
{
id port = info->receiver;
int port_fd_count = 128; // FIXME
int port_fd_array[port_fd_count];
if ([port respondsToSelector:
@selector(getFds:count:)])
{
[port getFds: port_fd_array
count: &port_fd_count];
}
NSDebugMLLog(@"NSRunLoop",
@"listening to %d port handles\n", port_fd_count);
while (port_fd_count--)
{
fd = port_fd_array[port_fd_count];
setPollfd(fd, POLLIN, self);
NSMapInsert(_rfdMap,
(void*)(intptr_t)port_fd_array[port_fd_count], info);
}
}
break;
}
}
}
@ -355,7 +355,7 @@ static void setPollfd(int fd, int event, GSRunLoopCtxt *ctxt)
* we can service the queue. Similarly, if a task has completed,
* we need to deliver its notifications.
*/
if (GSCheckTasks() || GSNotifyMore())
if (GSCheckTasks() || GSNotifyMore() || immediate == YES)
{
milliseconds = 0;
}
@ -369,7 +369,14 @@ static void setPollfd(int fd, int event, GSRunLoopCtxt *ctxt)
fprintf(stderr, "\n");
}
#endif
poll_return = poll (pollfds, pollfds_count, milliseconds);
if (pollfds_count > 0)
{
poll_return = poll (pollfds, pollfds_count, milliseconds);
}
else
{
poll_return = 0;
}
#if 0
{
unsigned int i;
@ -405,6 +412,42 @@ static void setPollfd(int fd, int event, GSRunLoopCtxt *ctxt)
}
}
/*
* Trigger any watchers which are set up to for every runloop wait.
*/
count = GSIArrayCount(_trigger);
while (completed == NO && count-- > 0)
{
GSRunLoopWatcher *watcher;
watcher = (GSRunLoopWatcher*)GSIArrayItemAtIndex(_trigger, count).obj;
if (watcher->_invalidated == NO)
{
i = [contexts count];
while (i-- > 0)
{
GSRunLoopCtxt *c = [contexts objectAtIndex: i];
if (c != self)
{
[c endEvent: (void*)watcher type: ET_TRIGGER];
}
}
/*
* 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];
}
GSNotifyASAP();
}
/*
* If the poll returned no descriptors with events, we have no more to do.
*/
if (poll_return == 0)
{
completed = YES;
@ -469,9 +512,10 @@ static void setPollfd(int fd, int event, GSRunLoopCtxt *ctxt)
* The watcher is still valid - so call its
* receivers event handling method.
*/
(*watcher->handleEvent)(watcher->receiver,
eventSel, watcher->data, watcher->type,
(void*)(uintptr_t)fd, mode);
[watcher->receiver receivedEvent: watcher->data
type: watcher->type
extra: (void*)(uintptr_t)fd
forMode: mode];
}
GSNotifyASAP();
if (completed == YES)
@ -500,9 +544,10 @@ static void setPollfd(int fd, int event, GSRunLoopCtxt *ctxt)
* The watcher is still valid - so call its
* receivers event handling method.
*/
(*watcher->handleEvent)(watcher->receiver,
eventSel, watcher->data, watcher->type,
(void*)(uintptr_t)fd, mode);
[watcher->receiver receivedEvent: watcher->data
type: watcher->type
extra: (void*)(uintptr_t)fd
forMode: mode];
}
GSNotifyASAP();
if (completed == YES)
@ -531,9 +576,10 @@ static void setPollfd(int fd, int event, GSRunLoopCtxt *ctxt)
* The watcher is still valid - so call its
* receivers event handling method.
*/
(*watcher->handleEvent)(watcher->receiver,
eventSel, watcher->data, watcher->type,
(void*)(uintptr_t)fd, mode);
[watcher->receiver receivedEvent: watcher->data
type: watcher->type
extra: (void*)(uintptr_t)fd
forMode: mode];
}
GSNotifyASAP();
if (completed == YES)
@ -572,9 +618,10 @@ static void setPollfd(int fd, int event, GSRunLoopCtxt *ctxt)
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.
int num_inputs = 0;
int fdEnd = -1;
unsigned count;
unsigned i;
BOOL immediate = NO;
i = GSIArrayCount(watchers);
@ -613,107 +660,85 @@ static void setPollfd(int fd, int event, GSRunLoopCtxt *ctxt)
NSResetMapTable(_efdMap);
NSResetMapTable(_rfdMap);
NSResetMapTable(_wfdMap);
GSIArrayRemoveAllItems(_trigger);
while (i-- > 0)
{
GSRunLoopWatcher *info;
int fd;
BOOL trigger;
info = GSIArrayItemAtIndex(watchers, i).obj;
if (info->_invalidated == YES)
{
GSIArrayRemoveItemAtIndex(watchers, i);
continue;
}
switch (info->type)
else if ([info runLoopShouldBlock: &trigger] == NO)
{
case ET_EDESC:
fd = (int)(intptr_t)info->data;
if (fd > fdEnd)
fdEnd = fd;
FD_SET (fd, &exception_fds);
NSMapInsert(_efdMap, (void*)(intptr_t)fd, info);
num_inputs++;
break;
if (trigger == YES)
{
immediate = YES;
GSIArrayAddItem(_trigger, (GSIArrayItem)(id)info);
}
}
else
{
switch (info->type)
{
case ET_EDESC:
fd = (int)(intptr_t)info->data;
if (fd > fdEnd)
fdEnd = fd;
FD_SET (fd, &exception_fds);
NSMapInsert(_efdMap, (void*)(intptr_t)fd, info);
break;
case ET_RDESC:
fd = (int)(intptr_t)info->data;
if (fd > fdEnd)
fdEnd = fd;
FD_SET (fd, &read_fds);
NSMapInsert(_rfdMap, (void*)(intptr_t)fd, info);
num_inputs++;
break;
case ET_WDESC:
fd = (int)(intptr_t)info->data;
if (fd > fdEnd)
fdEnd = fd;
FD_SET (fd, &write_fds);
NSMapInsert(_wfdMap, (void*)(intptr_t)fd, info);
num_inputs++;
break;
case ET_RPORT:
if ([info->receiver isValid] == NO)
{
/*
* We must remove an invalidated port.
*/
info->_invalidated = YES;
GSIArrayRemoveItemAtIndex(watchers, i);
}
else
{
id port = info->receiver;
int port_fd_count = 128; // xxx #define this constant
int port_fd_array[port_fd_count];
if ([port respondsToSelector:
@selector(getFds:count:)])
{
[port getFds: port_fd_array
count: &port_fd_count];
}
NSDebugMLLog(@"NSRunLoop", @"listening to %d port sockets",
port_fd_count);
while (port_fd_count--)
{
fd = port_fd_array[port_fd_count];
FD_SET (port_fd_array[port_fd_count], &read_fds);
if (fd > fdEnd)
fdEnd = fd;
NSMapInsert(_rfdMap,
(void*)(intptr_t)port_fd_array[port_fd_count], info);
num_inputs++;
}
}
break;
case ET_INSTREAM:
fd = [(NSStream*)info->data _fileDescriptor];
if (fd >= 0)
{
case ET_RDESC:
fd = (int)(intptr_t)info->data;
if (fd > fdEnd)
fdEnd = fd;
FD_SET (fd, &read_fds);
NSMapInsert(_rfdMap, (void*)(intptr_t)fd, info);
}
num_inputs++;
break;
break;
case ET_OUTSTREAM:
fd = [(NSStream*)info->data _fileDescriptor];
if (fd >= 0)
{
case ET_WDESC:
fd = (int)(intptr_t)info->data;
if (fd > fdEnd)
fdEnd = fd;
FD_SET (fd, &read_fds);
FD_SET (fd, &write_fds);
NSMapInsert(_wfdMap, (void*)(intptr_t)fd, info);
}
num_inputs++;
break;
break;
case ET_RPORT:
{
id port = info->receiver;
int port_fd_count = 128; // xxx #define this constant
int port_fd_array[port_fd_count];
if ([port respondsToSelector:
@selector(getFds:count:)])
{
[port getFds: port_fd_array
count: &port_fd_count];
}
NSDebugMLLog(@"NSRunLoop", @"listening to %d port sockets",
port_fd_count);
while (port_fd_count--)
{
fd = port_fd_array[port_fd_count];
FD_SET (port_fd_array[port_fd_count], &read_fds);
if (fd > fdEnd)
fdEnd = fd;
NSMapInsert(_rfdMap,
(void*)(intptr_t)port_fd_array[port_fd_count], info);
}
}
break;
case ET_TRIGGER:
break;
}
}
}
fdEnd++;
@ -724,7 +749,7 @@ static void setPollfd(int fd, int event, GSRunLoopCtxt *ctxt)
* we can service the queue. Similarly, if a task has completed,
* we need to deliver its notifications.
*/
if (GSCheckTasks() || GSNotifyMore())
if (GSCheckTasks() || GSNotifyMore() || immediate == YES)
{
timeout.tv_sec = 0;
timeout.tv_usec = 0;
@ -733,8 +758,15 @@ static void setPollfd(int fd, int event, GSRunLoopCtxt *ctxt)
// NSDebugMLLog(@"NSRunLoop", @"select timeout %d,%d", timeout.tv_sec, timeout.tv_usec);
select_return = select (fdEnd, &read_fds, &write_fds,
&exception_fds, select_timeout);
if (fdEnd >= 0)
{
select_return = select (fdEnd, &read_fds, &write_fds,
&exception_fds, select_timeout);
}
else
{
select_return = 0;
}
NSDebugMLLog(@"NSRunLoop", @"select returned %d", select_return);
@ -760,6 +792,43 @@ static void setPollfd(int fd, int event, GSRunLoopCtxt *ctxt)
abort ();
}
}
/*
* Trigger any watchers which are set up to for every runloop wait.
*/
count = GSIArrayCount(_trigger);
while (completed == NO && count-- > 0)
{
GSRunLoopWatcher *watcher;
watcher = (GSRunLoopWatcher*)GSIArrayItemAtIndex(_trigger, count).obj;
if (watcher->_invalidated == NO)
{
i = [contexts count];
while (i-- > 0)
{
GSRunLoopCtxt *c = [contexts objectAtIndex: i];
if (c != self)
{
[c endEvent: (void*)watcher type: ET_TRIGGER];
}
}
/*
* 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];
}
GSNotifyASAP();
}
/*
* If the select returned no descriptors with events, we have no more to do.
*/
if (select_return == 0)
{
completed = YES;
@ -794,7 +863,8 @@ static void setPollfd(int fd, int event, GSRunLoopCtxt *ctxt)
{
GSRunLoopWatcher *watcher;
watcher = (GSRunLoopWatcher*)NSMapGet(_efdMap, (void*)fdIndex);
watcher
= (GSRunLoopWatcher*)NSMapGet(_efdMap, (void*)(intptr_t)fdIndex);
if (watcher != nil && watcher->_invalidated == NO)
{
i = [contexts count];
@ -802,15 +872,17 @@ static void setPollfd(int fd, int event, GSRunLoopCtxt *ctxt)
{
GSRunLoopCtxt *c = [contexts objectAtIndex: i];
if (c != self) [c endEvent: (void*)fdIndex type: ET_EDESC];
if (c != self)
[c endEvent: (void*)(intptr_t)fdIndex type: ET_EDESC];
}
/*
* The watcher is still valid - so call its receivers
* event handling method.
*/
(*watcher->handleEvent)(watcher->receiver,
eventSel, watcher->data, watcher->type,
(void*)(uintptr_t)fdIndex, mode);
[watcher->receiver receivedEvent: watcher->data
type: watcher->type
extra: watcher->data
forMode: mode];
}
GSNotifyASAP();
if (completed == YES)
@ -823,7 +895,8 @@ static void setPollfd(int fd, int event, GSRunLoopCtxt *ctxt)
{
GSRunLoopWatcher *watcher;
watcher = (GSRunLoopWatcher*)NSMapGet(_wfdMap, (void*)fdIndex);
watcher
= (GSRunLoopWatcher*)NSMapGet(_wfdMap, (void*)(intptr_t)fdIndex);
if (watcher != nil && watcher->_invalidated == NO)
{
i = [contexts count];
@ -831,15 +904,17 @@ static void setPollfd(int fd, int event, GSRunLoopCtxt *ctxt)
{
GSRunLoopCtxt *c = [contexts objectAtIndex: i];
if (c != self) [c endEvent: (void*)fdIndex type: ET_WDESC];
if (c != self)
[c endEvent: (void*)(intptr_t)fdIndex type: ET_WDESC];
}
/*
* The watcher is still valid - so call its receivers
* event handling method.
*/
(*watcher->handleEvent)(watcher->receiver,
eventSel, watcher->data, watcher->type,
(void*)(uintptr_t)fdIndex, mode);
[watcher->receiver receivedEvent: watcher->data
type: watcher->type
extra: watcher->data
forMode: mode];
}
GSNotifyASAP();
if (completed == YES)
@ -852,7 +927,8 @@ static void setPollfd(int fd, int event, GSRunLoopCtxt *ctxt)
{
GSRunLoopWatcher *watcher;
watcher = (GSRunLoopWatcher*)NSMapGet(_rfdMap, (void*)fdIndex);
watcher
= (GSRunLoopWatcher*)NSMapGet(_rfdMap, (void*)(intptr_t)fdIndex);
if (watcher != nil && watcher->_invalidated == NO)
{
i = [contexts count];
@ -860,15 +936,17 @@ static void setPollfd(int fd, int event, GSRunLoopCtxt *ctxt)
{
GSRunLoopCtxt *c = [contexts objectAtIndex: i];
if (c != self) [c endEvent: (void*)fdIndex type: ET_RDESC];
if (c != self)
[c endEvent: (void*)(intptr_t)fdIndex type: ET_RDESC];
}
/*
* The watcher is still valid - so call its receivers
* event handling method.
*/
(*watcher->handleEvent)(watcher->receiver,
eventSel, watcher->data, watcher->type,
(void*)(uintptr_t)fdIndex, mode);
[watcher->receiver receivedEvent: watcher->data
type: watcher->type
extra: watcher->data
forMode: mode];
}
GSNotifyASAP();
if (completed == YES)

View file

@ -1,45 +0,0 @@
#include "config.h"
#include "GNUstepBase/preface.h"
#include "../GSRunLoopWatcher.h"
#include <Foundation/NSException.h>
#include <Foundation/NSPort.h>
SEL eventSel; /* Initialized in [NSRunLoop +initialize] */
@implementation GSRunLoopWatcher
- (void) dealloc
{
RELEASE(_date);
[super dealloc];
}
- (id) initWithType: (RunLoopEventType)aType
receiver: (id)anObj
data: (void*)item
{
_invalidated = NO;
switch (aType)
{
case ET_EDESC: type = aType; break;
case ET_RDESC: type = aType; break;
case ET_WDESC: type = aType; break;
case ET_RPORT: type = aType; break;
default:
[NSException raise: NSInvalidArgumentException
format: @"NSRunLoop - unknown event type"];
}
receiver = anObj;
if ([receiver respondsToSelector: eventSel] == YES)
handleEvent = [receiver methodForSelector: eventSel];
else
[NSException raise: NSInvalidArgumentException
format: @"RunLoop listener has no event handling method"];
data = item;
return self;
}
@end

File diff suppressed because it is too large Load diff