Libbarrett
1.2.4
|
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 }