threadedfilebuf.cpp
Go to the documentation of this file.
00001 /* This file is part of the Pangolin Project.
00002  * http://github.com/stevenlovegrove/Pangolin
00003  *
00004  * Copyright (c) 2011 Steven Lovegrove
00005  *
00006  * Permission is hereby granted, free of charge, to any person
00007  * obtaining a copy of this software and associated documentation
00008  * files (the "Software"), to deal in the Software without
00009  * restriction, including without limitation the rights to use,
00010  * copy, modify, merge, publish, distribute, sublicense, and/or sell
00011  * copies of the Software, and to permit persons to whom the
00012  * Software is furnished to do so, subject to the following
00013  * conditions:
00014  *
00015  * The above copyright notice and this permission notice shall be
00016  * included in all copies or substantial portions of the Software.
00017  *
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00019  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
00020  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00021  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
00022  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
00023  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00024  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00025  * OTHER DEALINGS IN THE SOFTWARE.
00026  */
00027 
00028 #include "threadedfilebuf.h"
00029 
00030 #include <cstring>
00031 
00032 using namespace std;
00033 
00034 namespace pangolin
00035 {
00036 
00037 threadedfilebuf::threadedfilebuf( const std::string& filename, unsigned int buffer_size_bytes )
00038     : mem_buffer(0), mem_size(0), mem_start(0), mem_end(0)
00039 {
00040     file.open(filename.c_str(), ios::out | ios::binary );
00041 
00042     mem_max_size = buffer_size_bytes;
00043     mem_buffer = new char[mem_max_size];
00044 
00045     write_thread = boost::thread(boost::ref(*this));
00046 }
00047 
00048 threadedfilebuf::~threadedfilebuf()
00049 {
00050     if( write_thread.joinable() )
00051     {
00052         write_thread.interrupt();
00053         write_thread.join();
00054     }
00055 
00056     if( mem_buffer) delete mem_buffer;
00057     file.close();
00058 }
00059 
00060 std::streamsize threadedfilebuf::xsputn(const char* data, std::streamsize num_bytes)
00061 {
00062     if( num_bytes > mem_max_size )
00063         throw exception();
00064 
00065     {
00066         boost::unique_lock<boost::mutex> lock(update_mutex);
00067 
00068         // wait until there is space to write into buffer
00069         while( mem_size + num_bytes > mem_max_size )
00070         {
00071             cond_dequeued.wait(lock);
00072         }
00073 
00074         // add image to end of mem_buffer
00075         const int array_a_size =
00076             (mem_start <= mem_end) ? (mem_max_size - mem_end) : (mem_start - mem_end);
00077 
00078         if( num_bytes <= array_a_size )
00079         {
00080             // copy in one
00081             memcpy(mem_buffer + mem_end, data, num_bytes);
00082             mem_end += num_bytes;
00083             mem_size += num_bytes;
00084         }
00085         else
00086         {
00087             const int array_b_size = num_bytes - array_a_size;
00088             memcpy(mem_buffer + mem_end, data, array_a_size);
00089             memcpy(mem_buffer, data+array_a_size, array_b_size);
00090             mem_end = array_b_size;
00091             mem_size += num_bytes;
00092         }
00093 
00094         if(mem_end == mem_max_size)
00095             mem_end = 0;
00096     }
00097 
00098     cond_queued.notify_one();
00099 
00100     return num_bytes;
00101 }
00102 
00103 void threadedfilebuf::operator()()
00104 {
00105     int data_to_write = 0;
00106 
00107     while(true)
00108     {
00109         {
00110             boost::unique_lock<boost::mutex> lock(update_mutex);
00111 
00112             while( mem_size == 0 )
00113                 cond_queued.wait(lock);
00114 
00115             data_to_write =
00116                 (mem_start < mem_end) ?
00117                 mem_end - mem_start :
00118                 mem_max_size - mem_start;
00119         }
00120 
00121         std::streamsize bytes_written =
00122             file.sputn(mem_buffer + mem_start, data_to_write );
00123 
00124         if( bytes_written != data_to_write)
00125             throw std::exception();
00126 
00127         {
00128             boost::unique_lock<boost::mutex> lock(update_mutex);
00129 
00130             mem_size -= data_to_write;
00131             mem_start += data_to_write;
00132 
00133             if(mem_start == mem_max_size)
00134                 mem_start = 0;
00135         }
00136 
00137         cond_dequeued.notify_all();
00138     }
00139 }
00140 
00141 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines


pangolin_wrapper
Author(s): Todor Stoyanov
autogenerated on Wed Feb 13 2013 14:03:25