#include <cutils/log.h>
#include <utils/Errors.h>
-audio_utils_fifo::audio_utils_fifo(uint32_t frameCount, uint32_t frameSize, void *buffer)
+audio_utils_fifo_base::audio_utils_fifo_base(uint32_t frameCount)
__attribute__((no_sanitize("integer"))) :
mFrameCount(frameCount), mFrameCountP2(roundup(frameCount)),
- mFudgeFactor(mFrameCountP2 - mFrameCount), mFrameSize(frameSize), mBuffer(buffer),
+ mFudgeFactor(mFrameCountP2 - mFrameCount),
mSharedRear(0), mThrottleFront(NULL)
{
- // maximum value of frameCount * frameSize is INT_MAX (2^31 - 1), not 2^31, because we need to
- // be able to distinguish successful and error return values from read and write.
- ALOG_ASSERT(frameCount > 0 && frameSize > 0 && buffer != NULL &&
- frameCount <= ((uint32_t) INT_MAX) / frameSize);
+ // actual upper bound on frameCount will depend on the frame size
+ ALOG_ASSERT(frameCount > 0 && frameCount <= ((uint32_t) INT_MAX));
}
-audio_utils_fifo::~audio_utils_fifo()
+audio_utils_fifo_base::~audio_utils_fifo_base()
{
}
-uint32_t audio_utils_fifo::sum(uint32_t index, uint32_t increment)
+uint32_t audio_utils_fifo_base::sum(uint32_t index, uint32_t increment)
__attribute__((no_sanitize("integer")))
{
if (mFudgeFactor) {
}
}
-int32_t audio_utils_fifo::diff(uint32_t rear, uint32_t front, size_t *lost)
+int32_t audio_utils_fifo_base::diff(uint32_t rear, uint32_t front, size_t *lost)
__attribute__((no_sanitize("integer")))
{
uint32_t diff = rear - front;
////////////////////////////////////////////////////////////////////////////////
+audio_utils_fifo::audio_utils_fifo(uint32_t frameCount, uint32_t frameSize, void *buffer)
+ __attribute__((no_sanitize("integer"))) :
+ audio_utils_fifo_base(frameCount), mFrameSize(frameSize), mBuffer(buffer)
+{
+ // maximum value of frameCount * frameSize is INT_MAX (2^31 - 1), not 2^31, because we need to
+ // be able to distinguish successful and error return values from read and write.
+ ALOG_ASSERT(frameCount > 0 && frameSize > 0 && buffer != NULL &&
+ frameCount <= ((uint32_t) INT_MAX) / frameSize);
+}
+
+audio_utils_fifo::~audio_utils_fifo()
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
audio_utils_fifo_provider::audio_utils_fifo_provider() :
mObtained(0)
{
#error C API is no longer supported
#endif
-// Single writer, single reader non-blocking FIFO.
-// Writer and reader must be in same process.
-
-// No user-serviceable parts within.
-class audio_utils_fifo {
-
- friend class audio_utils_fifo_reader;
- friend class audio_utils_fifo_writer;
-
-public:
-
-/**
- * Construct a FIFO object.
- *
- * \param frameCount Max number of significant frames to be stored in the FIFO > 0.
- * If writes and reads always use the same count, and that count is a divisor of
- * frameCount, then the writes and reads will never do a partial transfer.
- * \param frameSize Size of each frame in bytes > 0, and frameSize * frameCount <= INT_MAX.
- * \param buffer Pointer to a caller-allocated buffer of frameCount frames.
- */
- audio_utils_fifo(uint32_t frameCount, uint32_t frameSize, void *buffer);
+// Base class for single writer, single-reader or multi-reader non-blocking FIFO.
+// The base class manipulates frame indices only, and has no knowledge of frame sizes or the buffer.
- ~audio_utils_fifo();
+class audio_utils_fifo_base {
-private:
+protected:
+ audio_utils_fifo_base(uint32_t frameCount);
+ virtual ~audio_utils_fifo_base();
/** Return a new index as the sum of a validated index and a specified increment.
*
const uint32_t mFudgeFactor; // mFrameCountP2 - mFrameCount, the number of "wasted" frames
// after the end of mBuffer. Only the indices are wasted, not any
// memory.
- const uint32_t mFrameSize; // size of each frame in bytes
- void * const mBuffer; // pointer to caller-allocated buffer of size mFrameCount frames
std::atomic_uint_fast32_t mSharedRear; // accessed by both sides using atomic operations
std::atomic_uint_fast32_t *mThrottleFront;
};
+////////////////////////////////////////////////////////////////////////////////
+
+// Same as above, but understands frame sizes and knows about the buffer but does not own it.
+// Writer and reader must be in same process.
+
+class audio_utils_fifo : audio_utils_fifo_base {
+
+ friend class audio_utils_fifo_reader;
+ friend class audio_utils_fifo_writer;
+
+public:
+
+/**
+ * Construct a FIFO object.
+ *
+ * \param frameCount Max number of significant frames to be stored in the FIFO > 0.
+ * If writes and reads always use the same count, and that count is a divisor of
+ * frameCount, then the writes and reads will never do a partial transfer.
+ * \param frameSize Size of each frame in bytes > 0, and frameSize * frameCount <= INT_MAX.
+ * \param buffer Pointer to a caller-allocated buffer of frameCount frames.
+ */
+ audio_utils_fifo(uint32_t frameCount, uint32_t frameSize, void *buffer);
+
+ virtual ~audio_utils_fifo();
+
+private:
+
+ // These fields are const after initialization
+ const uint32_t mFrameSize; // size of each frame in bytes
+ void * const mBuffer; // pointer to caller-allocated buffer of size mFrameCount frames
+};
+
// Describes one virtually contiguous fragment of a logically contiguous slice.
// Compare to struct iovec for readv(2) and writev(2).
struct audio_utils_iovec {
public:
audio_utils_fifo_writer(audio_utils_fifo& fifo);
- ~audio_utils_fifo_writer();
+ virtual ~audio_utils_fifo_writer();
/**
* Write to FIFO.
public:
audio_utils_fifo_reader(audio_utils_fifo& fifo, bool throttlesWriter);
- ~audio_utils_fifo_reader();
+ virtual ~audio_utils_fifo_reader();
/** Read from FIFO.
*