diff deps/Platinum/Source/Core/PltRingBufferStream.cpp @ 0:3425707ddbf6

Initial import (hopefully this mercurial stuff works...)
author fraserofthenight
date Mon, 06 Jul 2009 08:06:28 -0700
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deps/Platinum/Source/Core/PltRingBufferStream.cpp	Mon Jul 06 08:06:28 2009 -0700
@@ -0,0 +1,213 @@
+/*****************************************************************
+|
+|   Platinum - Ring Buffer Stream
+|
+| Copyright (c) 2004-2008, Plutinosoft, LLC.
+| All rights reserved.
+| http://www.plutinosoft.com
+|
+| This program is free software; you can redistribute it and/or
+| modify it under the terms of the GNU General Public License
+| as published by the Free Software Foundation; either version 2
+| of the License, or (at your option) any later version.
+|
+| OEMs, ISVs, VARs and other distributors that combine and 
+| distribute commercially licensed software with Platinum software
+| and do not wish to distribute the source code for the commercially
+| licensed software under version 2, or (at your option) any later
+| version, of the GNU General Public License (the "GPL") must enter
+| into a commercial license agreement with Plutinosoft, LLC.
+| 
+| This program is distributed in the hope that it will be useful,
+| but WITHOUT ANY WARRANTY; without even the implied warranty of
+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+| GNU General Public License for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with this program; see the file LICENSE.txt. If not, write to
+| the Free Software Foundation, Inc., 
+| 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+| http://www.gnu.org/licenses/gpl-2.0.html
+|
+****************************************************************/
+
+/*----------------------------------------------------------------------
+|   includes
++---------------------------------------------------------------------*/
+#include "PltRingBufferStream.h"
+#include "Neptune.h"
+
+/*----------------------------------------------------------------------
+|   defines
++---------------------------------------------------------------------*/
+#ifdef max
+#undef max
+#endif
+#define max(a,b)    (((a) > (b)) ? (a) : (b))
+
+#ifdef min
+#undef min
+#endif
+#define min(a,b)    (((a) < (b)) ? (a) : (b))
+
+/*----------------------------------------------------------------------
+|   PLT_RingBufferStream::PLT_RingBufferStream
++---------------------------------------------------------------------*/
+PLT_RingBufferStream::PLT_RingBufferStream(NPT_Size buffer_size,
+                                           bool     blocking /* = true */) : 
+    m_TotalBytesRead(0),
+    m_TotalBytesWritten(0),
+    m_Eos(false),
+    m_Blocking(blocking)
+{
+    m_RingBuffer = new NPT_RingBuffer(buffer_size);
+}
+
+/*----------------------------------------------------------------------
+|   PLT_RingBufferStream::PLT_RingBufferStream
++---------------------------------------------------------------------*/
+PLT_RingBufferStream::PLT_RingBufferStream(NPT_RingBufferReference& buffer,
+                                           bool blocking /* = true */) : 
+    m_RingBuffer(buffer),
+    m_TotalBytesRead(0),
+    m_TotalBytesWritten(0),
+    m_Eos(false),
+    m_Blocking(blocking)
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_RingBufferStream::~PLT_RingBufferStream
++---------------------------------------------------------------------*/
+PLT_RingBufferStream::~PLT_RingBufferStream()
+{
+}
+
+/*----------------------------------------------------------------------
+|   PLT_RingBufferStream::Read
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_RingBufferStream::Read(void*     buffer, 
+                           NPT_Size  max_bytes_to_read, 
+                           NPT_Size* bytes_read /*= NULL*/)
+{
+    NPT_Size bytes_avail, to_read;
+    NPT_Size last_read = 0;
+
+    // reset output param first
+    if (bytes_read) *bytes_read = 0;
+
+    // wait for data
+    do {
+        {
+            NPT_AutoLock autoLock(m_Lock);
+            if (m_RingBuffer->GetContiguousAvailable()) break;
+        }
+
+        if (m_Eos || m_RingBuffer->IsClosed()) {
+            return NPT_ERROR_EOS;
+        } else if (!m_Blocking) {
+            return NPT_ERROR_WOULD_BLOCK;
+        }
+
+        // sleep and try again
+        NPT_System::Sleep(NPT_TimeInterval(0, 10000));
+    } while (1);
+
+    {
+        NPT_AutoLock autoLock(m_Lock);
+
+        // try twice in case we looped
+        for (int i=0; i<2; i++) {
+            bytes_avail = m_RingBuffer->GetContiguousAvailable();
+            to_read = min(max_bytes_to_read - last_read, bytes_avail);
+
+            // break if nothing to read
+            if (to_read == 0) break;
+
+            // read into buffer and advance
+            NPT_CHECK(m_RingBuffer->Read((unsigned char*)buffer+last_read, to_read));
+
+            // keep track of the total bytes we have read so far
+            m_TotalBytesRead += to_read;
+            last_read += to_read;
+
+            if (bytes_read) *bytes_read += to_read;
+        }
+    }
+
+    // we have read some chars, so return success
+    // even if we have read less than asked
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_RingBufferStream::Write
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_RingBufferStream::Write(const void* buffer, 
+                            NPT_Size    bytes_to_write, 
+                            NPT_Size*   bytes_written /*= NULL*/)
+{
+    NPT_Size     space_avail, to_write;
+    NPT_Size     last_written = 0;
+
+    // reset output param first
+    if (bytes_written) *bytes_written = 0;
+
+    // wait for space
+    do {
+        {
+            NPT_AutoLock autoLock(m_Lock);
+            if (m_RingBuffer->GetContiguousSpace()) break;
+        }
+
+        if (m_Eos || m_RingBuffer->IsClosed()) {
+            return NPT_ERROR_EOS;
+        } else if (!m_Blocking) {
+            return NPT_ERROR_WOULD_BLOCK;
+        }
+
+        // sleep and try again
+        NPT_System::Sleep(NPT_TimeInterval(0, 10000));
+    } while (1);
+
+    {
+        NPT_AutoLock autoLock(m_Lock);
+
+        // try twice in case we looped
+        for (int i=0; i<2; i++) {
+            space_avail = m_RingBuffer->GetContiguousSpace();
+            to_write = min(bytes_to_write - last_written, space_avail);
+
+            // break if no space to write
+            if (to_write == 0) break;
+
+            // write into buffer
+            NPT_CHECK(m_RingBuffer->Write((unsigned char*)buffer+last_written, to_write));
+
+            m_TotalBytesWritten += to_write; 
+            last_written += to_write;
+
+            if (bytes_written) *bytes_written += to_write;
+        }
+    }
+
+    // we have written some chars, so return success
+    // even if we have written less than provided
+    return NPT_SUCCESS;
+}
+
+/*----------------------------------------------------------------------
+|   PLT_RingBufferStream::Flush
++---------------------------------------------------------------------*/
+NPT_Result 
+PLT_RingBufferStream::Flush()
+{
+    NPT_AutoLock autoLock(m_Lock);
+
+    m_RingBuffer->Flush();
+    m_TotalBytesRead = 0;
+    m_TotalBytesWritten = 0;
+    return NPT_SUCCESS;
+}