This version fixes a bug in #close that causes the coroutine to not get unwound when the stream is closed. �Also, it now uses the stream itself as a marker instead of a special string (a suggestion from Eliot). �I've also created unit tests (which is how I caught the problem with close). �Below is the class comment:
-----
I enable the use of a ReadStream interface in cases where enumeration protocol is available, but no read stream interface is available. �For example, I can adapt any object that supports #do: for enumeration:
CoroutineReadStream on: #(1 2 3) iterator: #do:
The implementation makes use of coroutines to avoid the need to create and schedule a separate Process. �Sending #close will abandon the coroutine and unwind all contexts in the coroutine. �The coroutine is not invoked until the first request for an object. �The iterator is finished when there is an attempt to read past the end (via #next or #peek), or when there is an #atEnd test after the last object was retrieved.
A CoroutineReadSteam is not particularly efficient due to its use of thisContext and how stacks are optimized in most Smalltalk implementations.
Instance Variables:
nextValue <Object | noObjectMarker> Holds the next value to be answered when #next is called (needed to support #peek and #atEnd)...if it holds the noObjectMarker, it inticates that the coroutine needs to be invoked to get the next object.
suspendedContext <ContextPart> This is either the context of the iterating stack (when not actively retrieving the next object for a client) or the stack of the user of the stream (when of retrieving the next object)
homeContext <MethodContext> Holds the context of #initializeForBlock: called during instantiation and is used to ensure that exception propagation and handling works as one would expect.
Copyright (c) 2009 Stephen Pair
�Permission is hereby granted, free of charge, to any person
�obtaining a copy of this software and associated documentation
�files (the "Software"), to deal in the Software without
�restriction, including without limitation the rights to use,
�copy, modify, merge, publish, distribute, sublicense, and/or sell
�copies of the Software, and to permit persons to whom the
�Software is furnished to do so, subject to the following
�conditions:
�The above copyright notice and this permission notice shall be
�included in all copies or substantial portions of the Software.
�THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
�EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
�OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
�NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
�HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
�WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
�FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
�OTHER DEALINGS IN THE SOFTWARE.
- Stephen