MTBuffer is an abstract class that implements a generalized, thread-safe, flow-controlled, fixed-size buffer.
MTBuffer is intended to be subclassed to store and retrieve actual data. MTBuffer is based on the notion of an abstract frame, which may be a byte, or an arbitrary number of simultaneous, de-interleaved audio samples, or in fact anything that can be sequential. An MTBuffer is structured as a finite ring of abstract frames. The nature of the ring is hidden from the outside; it is an implementation detail. Wrap-around at the end of the ring is handled by MTBuffer; most subclasses will be able to ignore this.
Multiple threads may read and write on an MTBuffer simultaneously. Their operations will be coordinated and consistent, unless the MTBuffer is configured for single-threaded operation. A single-threaded MTBuffer is intended to be used in one thread only, or protected with external synchronization. Single-threaded mode is an optimization to avoid taking and releasing locks unnecessarily. Note that flow control is disabled in this mode; that is, read and write operations behave in the non-waiting manner.
An MTBuffer can hold up to a fixed number of abstract frames simultaneously. However, when using waiting operations, an arbitrary number of abstract frames may flow from a writer thread to a reader thread in a single method invocation. When writing frames, if the buffer fills to capacity, it can either wait for room to become available by another thread reading, or just do as much as it can immediately. Unread data in the buffer will not be overwritten. Likewise, when reading frames, if the buffer becomes empty, it can either wait for more data to be written, or just do as much as it can immediately with data on hand. Reading and writing operations signal each other to convey the availability, or lack thereof, of data and free space.
A subclass should provide its designated initializer to initialize its actual buffer and any other data
needed. It should invoke
[super initWithCapacity:]. A subclass
must provide concrete methods specific to its nature for reading and writing. These methods will create
a context block, specific to the subclass and opaque to MTBuffer, that will be passed by way of MTBuffer's
to the subclass's
methods. These methods implement the
actual data copying between user data and the concrete buffer.
See the implementation of MTByteBuffer for an example of a concrete subclass of MTBuffer.
- (void) bufferDidEmpty
- (unsigned) capacity
- (void) close
- (void) configureForSingleThreadedOperation
- (unsigned) count
- (void) flush
- (id) initWithCapacity:(unsigned)capacity
- (Boolean) isClosed
YESif close has been sent to the receiver, and
- (void) performReadToContext:(void *)theContext offset:(unsigned)theOffset count:(unsigned)count
- (void) performWriteFromContext:(void *)theContext offset:(unsigned)theOffset count:(unsigned)count
- (unsigned) readToContext:(void *)theContext count:(unsigned)count waitForData:(Boolean)wait
NO, then a maximum of [receiver count] frames will be copied into theContext. If wait is
YESand the receiver has not been closed, then all of the requested frames will be copied, pausing as necessary for frames from writeFromContext:count:waitForRoom:s to be added to the buffer. May cause bufferDidEmpty to be sent to the receiver one or more times, if the buffer becomes empty, is refilled, empties again, etc. while this method is processed. Returns the number of frames copied.
- (unsigned) writeFromContext:(void *)theContext count:(unsigned)count waitForRoom:(Boolean)wait
NO, then a maximum of the currently available space in the buffer will be copied from theContext. If wait is
YESand the receiver has not been closed, then all of the requested frames will be copied, pausing as necessary for space to become available by readToContext:count:waitForData:s removing frames from the buffer. Returns the number of frames copied.