Libbarrett  1.2.4
include/barrett/log/detail/real_time_writer-inl.h
Go to the documentation of this file.
00001 
00034 #include <stdexcept>
00035 #include <algorithm>
00036 #include <fstream>
00037 #include <string>
00038 
00039 #include <boost/bind.hpp>
00040 #include <boost/thread.hpp>
00041 #include <boost/lexical_cast.hpp>
00042 
00043 #include <barrett/os.h>
00044 
00045 
00046 namespace barrett {
00047 namespace log {
00048 
00049 
00050 template<typename T, typename Traits>
00051 RealTimeWriter<T, Traits>::RealTimeWriter(const char* fileName, double recordPeriod_s, int priority_) :
00052         Writer<T, Traits>(fileName), period(0.0), singleBufferSize(0),
00053         inBuff(NULL), outBuff(NULL), endInBuff(NULL), endOutBuff(NULL), currentPos(NULL), writeToDisk(false),
00054         thread(), priority(priority_)
00055 {
00056         if (this->recordLength > 1024) {
00057                 throw(std::logic_error("(log::RealTimeWriter::RealTimeWriter()): This constructor was not designed for records this big."));
00058         }
00059 
00060         // keep the single buffer size below 16KB
00061         size_t recordsInSingleBuffer = 16384 / this->recordLength;
00062 
00063         // with a factor of safety of 5, how many seconds to fill a single buffer?
00064         period = (recordsInSingleBuffer * recordPeriod_s) / 5.0;
00065         if (period < 0.003) {
00066                 throw(std::logic_error("(log::RealTimeWriter::RealTimeWriter()): This constructor was not designed for data rates this high."));
00067         }
00068         period = std::min(period, 1.0);  // limit period to a maximum of 1 second
00069 
00070         init(recordsInSingleBuffer);
00071 }
00072 
00073 template<typename T, typename Traits>
00074 RealTimeWriter<T, Traits>::RealTimeWriter(const char* fileName, double approxPeriod_s, size_t recordsInSingleBuffer, int priority_) :
00075         Writer<T, Traits>(fileName), period(approxPeriod_s),
00076         inBuff(NULL), outBuff(NULL), endInBuff(NULL), endOutBuff(NULL), currentPos(NULL), writeToDisk(false),
00077         thread(), priority(priority_)
00078 {
00079         init(recordsInSingleBuffer);
00080 }
00081 
00082 template<typename T, typename Traits>
00083 void RealTimeWriter<T, Traits>::init(size_t recordsInSingleBuffer) {
00084         singleBufferSize = this->recordLength * recordsInSingleBuffer;
00085 
00086         delete[] this->buffer;
00087         this->buffer = new char[singleBufferSize * 2];  // log::Writer's dtor will delete this for us.
00088 
00089         inBuff = this->buffer;
00090         outBuff = inBuff + singleBufferSize;
00091         endInBuff = inBuff + singleBufferSize;
00092         endOutBuff = outBuff + singleBufferSize;
00093         currentPos = inBuff;
00094         writeToDisk = false;
00095 
00096         // start writing thread
00097         boost::thread tmpThread(boost::bind(&RealTimeWriter<T, Traits>::writeToDiskEntryPoint, this));
00098         thread.swap(tmpThread);
00099 }
00100 
00101 template<typename T, typename Traits>
00102 RealTimeWriter<T, Traits>::~RealTimeWriter()
00103 {
00104         if (this->file.is_open()) {
00105                 close();
00106         }
00107 }
00108 
00109 template<typename T, typename Traits>
00110 void RealTimeWriter<T, Traits>::putRecord(parameter_type data)
00111 {
00112         Traits::serialize(data, currentPos);
00113         currentPos += this->recordLength;
00114 
00115         if (currentPos >= endInBuff) {
00116                 if (writeToDisk) {
00117                         throw(std::overflow_error("(log::RealTimeWriter::putRecord()): The input buffer filled up before the output buffer was written to disk."));
00118                 }
00119 
00120                 std::swap(inBuff, outBuff);
00121                 std::swap(endInBuff, endOutBuff);
00122                 currentPos = inBuff;
00123                 writeToDisk = true;
00124         }
00125 }
00126 
00127 template<typename T, typename Traits>
00128 void RealTimeWriter<T, Traits>::close()
00129 {
00130         thread.interrupt();
00131         thread.join();
00132 
00133         if (writeToDisk) {
00134                 this->file.write(outBuff, singleBufferSize);
00135                 writeToDisk = false;
00136         }
00137         if (currentPos != inBuff) {
00138                 this->file.write(inBuff, currentPos - inBuff);
00139         }
00140 
00141         this->Writer<T, Traits>::close();
00142 }
00143 
00144 template<typename T, typename Traits>
00145 void RealTimeWriter<T, Traits>::writeToDiskEntryPoint()
00146 {
00147         PeriodicLoopTimer loopTimer(period, priority);
00148         while ( !boost::this_thread::interruption_requested() ) {
00149                 loopTimer.wait();
00150                 if (writeToDisk) {
00151                         this->file.write(outBuff, singleBufferSize);
00152                         writeToDisk = false;
00153                 }
00154         }
00155 }
00156 
00157 
00158 }
00159 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Defines