# MTBuffer

MTBuffer is an abstract class that implements a generalized, thread-safe, flow-controlled, fixed-size buffer.

## Discussion

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.

#### Subclassing Guidelines

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 readToContext:count:waitForData: and writeFromContext:count:waitForRoom: to the subclass's performReadToContext:offset:count: and performWriteFromContext:offset:count: 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.

## Method Types

- Creating instances
  - - initWithCapacity:
- Working with attributes
  - - capacity
  - - count
- Working with data
  - - close
  - - isClosed
  - - configureForSingleThreadedOperation
  - - flush
  - - readToContext:count:waitForData:
  - - writeFromContext:count:waitForRoom:
- Methods to be implemented by subclasses
  - - bufferDidEmpty
  - - performReadToContext:offset:count:
  - - performWriteFromContext:offset:count:

## Instance Methods

### bufferDidEmpty

`- (void) bufferDidEmpty`
You should never send this message directly. Method to be implemented by subclasses, to perform any needed housekeeping or any other function. This message is sent when a read operation leaves the buffer empty. This message is sent while the buffer is is locked, so care should be taken not to perform non-real-time-safe operations if the buffer may be used with real-time constraints. The default implementation does nothing.

### capacity

`- (unsigned) capacity`
Returns the capacity of the receiver in abstract frames.

### close

`- (void) close`
Indicates to the receiver that no more abstract frames will be written into the buffer. This causes reading and writing operations to behave in the non-waiting manner, even if waiting is requested. Operations in progress and waiting for data or room will complete with whatever they were able to accomplish up to that point. Further writes will not succeed. Any abstract frames remaining in the receiver may be read out.

### configureForSingleThreadedOperation

`- (void) configureForSingleThreadedOperation`
Disables the receiver's synchronization interlocks and causes reading and writing operations to behave in the non-waiting manner, even if waiting is requested.

### count

`- (unsigned) count`
Returns the number of abstract frames currently stored in the receiver.

### flush

`- (void) flush`
Empties the receiver. Sends bufferDidEmpty to the receiver.

### initWithCapacity:

`- (id) initWithCapacity:(unsigned)capacity`
Initializes a newly allocated buffer with space for capacity abstract frames. This is the designated initializer.

### isClosed

`- (Boolean) isClosed`
Returns `YES` if close has been sent to the receiver, and `NO` otherwise.

### performReadToContext:offset:count:

`- (void) performReadToContext:(void *)theContext offset:(unsigned)theOffset count:(unsigned)count`
You should never send this message directly. Subclasses must override this method to implement the actual data copying appropriate for that class. This message is sent to the receiver by readToContext:count:waitForData: one or more times to copy count sequential abstract frames from the receiver's buffer, starting at abstract frame theOffset, to the current position in theContext. The implementation is responsible for advancing the current position in theContext by count abstract frames in the appropriate manner. theOffset plus count will not exceed the capacity of the buffer, nor count. The default implementation of this method does nothing.

### performWriteFromContext:offset:count:

`- (void) performWriteFromContext:(void *)theContext offset:(unsigned)theOffset count:(unsigned)count`
You should never send this message directly. Subclasses must override this method to implement the actual data copying appropriate for that class. This message is sent to the receiver by writeFromContext:count:waitForRoom: one or more times to copy count sequential abstract frames from the current position in theContext into the receiver's buffer, starting at abstract frame theOffset of the receiver's buffer. The implementation is responsible for advancing the current position in theContext by count abstract frames in the appropriate manner. theOffset plus count will not exceed the capacity of the buffer, nor the amount of room remaining. The default implementation of this method does nothing.

### readToContext:count:waitForData:

`- (unsigned) readToContext:(void *)theContext count:(unsigned)count waitForData:(Boolean)wait`
You should never send this message directly. Subclasses will send this message to self to cause count abstract frames to be copied from the receiver's buffer into theContext by sending performReadToContext:offset:count: to the receiver as many times as necessary. If wait is `NO`, then a maximum of [receiver count] frames will be copied into theContext. If wait is `YES` and 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.

### writeFromContext:count:waitForRoom:

`- (unsigned) writeFromContext:(void *)theContext count:(unsigned)count waitForRoom:(Boolean)wait`
You should never send this message directly. Subclasses will send this message to self to cause count abstract frames to be copied from theContext into the receiver's buffer by sending performWriteFromContext:offset:count: to the receiver as many times as necessary. If wait is `NO`, then a maximum of the currently available space in the buffer will be copied from theContext. If wait is `YES` and 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.

Mike > Mac OS X > MTCoreAudio.framework > MTBuffer