diff --git a/Source/GSStream.h b/Source/GSStream.h index de1895bf7..5b537a27a 100644 --- a/Source/GSStream.h +++ b/Source/GSStream.h @@ -76,6 +76,7 @@ id _delegate; /* Delegate controls operation. */\ NSMutableDictionary *_properties; /* storage for properties */\ BOOL _delegateValid; /* whether the delegate responds*/\ + BOOL _scheduled; /* Are the loops sceduled? */\ NSError *_lastError; /* last error occured */\ NSStreamStatus _currentStatus;/* current status */\ NSMapTable *_loops; /* Run loops and their modes. */\ @@ -125,6 +126,15 @@ IVARS */ - (void) _schedule; +/** Return YES if the stream is *actually* scheduled in one or more loops. + */ +- (BOOL) _scheduled; + +/** Low level method to place the stream in the scheduled runloop. + * Must only be called by -_schedule and -scheduleInRunLoop:forMode: + */ +- (void) _scheduleInRunLoop: (NSRunLoop*)aRunLoop forMode: (NSString*)mode; + /** * send an event to delegate */ @@ -152,6 +162,11 @@ IVARS - (void) _recordError; - (void) _recordError: (NSError*)anError; +/** Low level method to remove the stream from the scheduled runloop. + * Must only be called by -_sunchedule and -removeFromRunLoop:forMode: + */ +- (void) _removeFromRunLoop: (NSRunLoop*)aRunLoop forMode: (NSString*)mode; + /** * say whether there is unhandled data for the stream. */ diff --git a/Source/GSStream.m b/Source/GSStream.m index b527a9b96..e7154d39e 100644 --- a/Source/GSStream.m +++ b/Source/GSStream.m @@ -113,8 +113,7 @@ static RunLoopEventType typeForStream(NSStream *aStream) RunLoopEventType type = typeForStream(aStream); void *event = [aStream _loopID]; - NSDebugMLLog(@"NSStream", - @"-addStream:mode: %@ (type %d) to %@ mode %@", + NSDebugMLLog(@"NSStream", @"%@ (type %d) to %@ mode %@", aStream, type, self, mode); [self addEvent: event type: type @@ -241,13 +240,17 @@ static RunLoopEventType typeForStream(NSStream *aStream) modes = (NSMutableArray*)NSMapGet(_loops, (void*)aRunLoop); if ([modes containsObject: mode]) { - [aRunLoop removeStream: self mode: mode]; + [self _removeFromRunLoop: aRunLoop forMode: mode]; [modes removeObject: mode]; if ([modes count] == 0) { NSMapRemove(_loops, (void*)aRunLoop); } } + if (NSCountMapTable(_loops) == 0) + { + _scheduled = NO; + } } } @@ -275,7 +278,7 @@ static RunLoopEventType typeForStream(NSStream *aStream) */ if ([self _isOpened]) { - [aRunLoop addStream: self mode: mode]; + [self _scheduleInRunLoop: aRunLoop forMode: mode]; } } } @@ -485,6 +488,11 @@ static RunLoopEventType typeForStream(NSStream *aStream) [self _setStatus: NSStreamStatusError]; } +- (void) _removeFromRunLoop: (NSRunLoop *)aRunLoop forMode: (NSString *)mode +{ + [aRunLoop removeStream: self mode: mode]; +} + - (void) _resetEvents: (NSUInteger)mask { _events &= ~mask; @@ -503,12 +511,23 @@ static RunLoopEventType typeForStream(NSStream *aStream) while (i-- > 0) { - [k addStream: self mode: [v objectAtIndex: i]]; + [self _scheduleInRunLoop: k forMode: [v objectAtIndex: i]]; } } NSEndMapTableEnumeration(&enumerator); } +- (BOOL) _scheduled +{ + return _scheduled; +} + +- (void) _scheduleInRunLoop: (NSRunLoop*)loop forMode: (NSString*)mode +{ + [loop addStream: self mode: mode]; + _scheduled = YES; +} + - (void) _sendEvent: (NSStreamEvent)event { [self _sendEvent: event delegate: _delegateValid == YES ? _delegate : nil]; @@ -516,6 +535,8 @@ static RunLoopEventType typeForStream(NSStream *aStream) - (void) _sendEvent: (NSStreamEvent)event delegate: (id)delegate { + NSDebugMLLog(@"NSStream", + @"%@ sendEvent %@", self, [self stringFromEvent:event]); if (event == NSStreamEventNone) { return; @@ -658,6 +679,7 @@ static RunLoopEventType typeForStream(NSStream *aStream) } } NSEndMapTableEnumeration(&enumerator); + _scheduled = NO; } - (BOOL) runLoopShouldBlock: (BOOL*)trigger