summaryrefslogtreecommitdiffstats
path: root/lib/base/fifo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/base/fifo.cpp')
-rw-r--r--lib/base/fifo.cpp124
1 files changed, 124 insertions, 0 deletions
diff --git a/lib/base/fifo.cpp b/lib/base/fifo.cpp
new file mode 100644
index 0000000..8653f51
--- /dev/null
+++ b/lib/base/fifo.cpp
@@ -0,0 +1,124 @@
+/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
+
+#include "base/fifo.hpp"
+
+using namespace icinga;
+
+/**
+ * Destructor for the FIFO class.
+ */
+FIFO::~FIFO()
+{
+ free(m_Buffer);
+}
+
+/**
+ * Resizes the FIFO's buffer so that it is at least newSize bytes long.
+ *
+ * @param newSize The minimum new size of the FIFO buffer.
+ */
+void FIFO::ResizeBuffer(size_t newSize, bool decrease)
+{
+ if (m_AllocSize >= newSize && !decrease)
+ return;
+
+ newSize = (newSize / FIFO::BlockSize + 1) * FIFO::BlockSize;
+
+ if (newSize == m_AllocSize)
+ return;
+
+ auto *newBuffer = static_cast<char *>(realloc(m_Buffer, newSize));
+
+ if (!newBuffer)
+ BOOST_THROW_EXCEPTION(std::bad_alloc());
+
+ m_Buffer = newBuffer;
+
+ m_AllocSize = newSize;
+}
+
+/**
+ * Optimizes memory usage of the FIFO buffer by reallocating
+ * and moving the buffer.
+ */
+void FIFO::Optimize()
+{
+ if (m_Offset > m_DataSize / 10 && m_Offset - m_DataSize > 1024) {
+ std::memmove(m_Buffer, m_Buffer + m_Offset, m_DataSize);
+ m_Offset = 0;
+
+ if (m_DataSize > 0)
+ ResizeBuffer(m_DataSize, true);
+
+ return;
+ }
+}
+
+size_t FIFO::Peek(void *buffer, size_t count, bool allow_partial)
+{
+ ASSERT(allow_partial);
+
+ if (count > m_DataSize)
+ count = m_DataSize;
+
+ if (buffer)
+ std::memcpy(buffer, m_Buffer + m_Offset, count);
+
+ return count;
+}
+
+/**
+ * Implements IOQueue::Read.
+ */
+size_t FIFO::Read(void *buffer, size_t count, bool allow_partial)
+{
+ ASSERT(allow_partial);
+
+ if (count > m_DataSize)
+ count = m_DataSize;
+
+ if (buffer)
+ std::memcpy(buffer, m_Buffer + m_Offset, count);
+
+ m_DataSize -= count;
+ m_Offset += count;
+
+ Optimize();
+
+ return count;
+}
+
+/**
+ * Implements IOQueue::Write.
+ */
+void FIFO::Write(const void *buffer, size_t count)
+{
+ ResizeBuffer(m_Offset + m_DataSize + count, false);
+ std::memcpy(m_Buffer + m_Offset + m_DataSize, buffer, count);
+ m_DataSize += count;
+
+ SignalDataAvailable();
+}
+
+void FIFO::Close()
+{ }
+
+bool FIFO::IsEof() const
+{
+ return false;
+}
+
+size_t FIFO::GetAvailableBytes() const
+{
+ return m_DataSize;
+}
+
+bool FIFO::SupportsWaiting() const
+{
+ return true;
+}
+
+bool FIFO::IsDataAvailable() const
+{
+ return m_DataSize > 0;
+}