annotate core/WriteFile.cpp @ 175:9bfe04d184fb experimental-fixing-AuxiliaryTask

Demonstrates issue #1374
author Giulio Moro <giuliomoro@yahoo.it>
date Mon, 28 Dec 2015 15:00:34 +0100
parents 1e7db6610600
children
rev   line source
giuliomoro@153 1 /*
giuliomoro@153 2 * WriteFile.cpp
giuliomoro@153 3 *
giuliomoro@153 4 * Created on: 5 Oct 2015
giuliomoro@153 5 * Author: giulio
giuliomoro@153 6 */
giuliomoro@153 7
giuliomoro@153 8 #include "WriteFile.h"
giuliomoro@153 9 //initialise static members
giuliomoro@153 10 bool WriteFile::staticConstructed=false;
giuliomoro@153 11 AuxiliaryTask WriteFile::writeAllFilesTask=NULL;
giuliomoro@153 12 std::vector<WriteFile *> WriteFile::objAddrs(0);
giuliomoro@153 13 bool WriteFile::threadRunning;
giuliomoro@153 14 bool WriteFile::threadIsExiting;
giuliomoro@153 15 int WriteFile::sleepTimeMs;
giuliomoro@153 16
giuliomoro@153 17 void WriteFile::staticConstructor(){
giuliomoro@153 18 if(staticConstructed==true)
giuliomoro@153 19 return;
giuliomoro@153 20 staticConstructed=true;
giuliomoro@153 21 threadIsExiting=false;
giuliomoro@153 22 threadRunning=false;
giuliomoro@153 23 writeAllFilesTask = BeagleRT_createAuxiliaryTask(WriteFile::run, 60, "writeAllFilesTask");
giuliomoro@175 24 printf("After writeAllFilesTask\n");
giuliomoro@175 25 dumpAuxTasks();
giuliomoro@153 26 }
giuliomoro@153 27
giuliomoro@153 28 WriteFile::WriteFile(){
giuliomoro@153 29 buffer = NULL;
giuliomoro@153 30 format = NULL;
giuliomoro@153 31 header = NULL;
giuliomoro@153 32 footer = NULL;
giuliomoro@153 33 stringBuffer = NULL;
giuliomoro@175 34 staticConstructor(); //TODO: this line should be in the constructor, but cannot be because of a bug in BeagleRT
giuliomoro@153 35 };
giuliomoro@153 36
giuliomoro@153 37 void WriteFile::init(const char* filename){ //if you do not call this before using the object, results are undefined
giuliomoro@153 38 file = fopen(filename, "w");
giuliomoro@153 39 variableOpen = false;
giuliomoro@153 40 lineLength = 0;
giuliomoro@159 41 setEcho(false);
giuliomoro@153 42 bufferLength = 0;
giuliomoro@157 43 textReadPointer = 0;
giuliomoro@157 44 binaryReadPointer = 0;
giuliomoro@153 45 writePointer = 0;
giuliomoro@153 46 sleepTimeMs = 1;
giuliomoro@153 47 stringBufferLength = 1000;
giuliomoro@153 48 stringBuffer = (char*)malloc(sizeof(char) * (stringBufferLength));
giuliomoro@153 49 setHeader("variable=[\n");
giuliomoro@153 50 setFooter("];\n");
giuliomoro@153 51 objAddrs.push_back(this);
giuliomoro@157 52 echoedLines = 0;
giuliomoro@157 53 echoPeriod = 1;
giuliomoro@153 54 }
giuliomoro@153 55
giuliomoro@157 56 void WriteFile::setFileType(WriteFileType newFileType){
giuliomoro@157 57 fileType = newFileType;
giuliomoro@159 58 if(fileType == kBinary)
giuliomoro@159 59 setLineLength(1);
giuliomoro@157 60 }
giuliomoro@153 61 void WriteFile::setEcho(bool newEcho){
giuliomoro@153 62 echo=newEcho;
giuliomoro@153 63 }
giuliomoro@157 64 void WriteFile::setEchoInterval(int newEchoPeriod){
giuliomoro@157 65 echoPeriod = newEchoPeriod;
giuliomoro@157 66 if(echoPeriod != 0)
giuliomoro@157 67 echo = true;
giuliomoro@157 68 else
giuliomoro@157 69 echo = false;
giuliomoro@157 70 }
giuliomoro@153 71 void WriteFile::print(const char* string){
giuliomoro@153 72 if(echo == true){
giuliomoro@157 73 echoedLines++;
giuliomoro@157 74 if (echoedLines >= echoPeriod){
giuliomoro@157 75 echoedLines = 0;
giuliomoro@157 76 printf("%s", string);
giuliomoro@157 77 }
giuliomoro@153 78 }
giuliomoro@157 79 if(file != NULL && fileType != kBinary){
giuliomoro@153 80 fprintf(file, "%s", string);
giuliomoro@153 81 }
giuliomoro@153 82 }
giuliomoro@153 83
giuliomoro@153 84 void WriteFile::writeLine(){
giuliomoro@157 85 if(echo == true || fileType != kBinary){
giuliomoro@157 86 int stringBufferPointer = 0;
giuliomoro@157 87 for(unsigned int n = 0; n < formatTokens.size(); n++){
giuliomoro@157 88 int numOfCharsWritten = snprintf( &stringBuffer[stringBufferPointer], stringBufferLength - stringBufferPointer,
giuliomoro@157 89 formatTokens[n], buffer[textReadPointer]);
giuliomoro@157 90 stringBufferPointer += numOfCharsWritten;
giuliomoro@157 91 textReadPointer++;
giuliomoro@159 92 if(textReadPointer >= bufferLength){
giuliomoro@157 93 textReadPointer -= bufferLength;
giuliomoro@157 94 }
giuliomoro@153 95 }
giuliomoro@157 96 print(stringBuffer);
giuliomoro@153 97 }
giuliomoro@153 98 }
giuliomoro@153 99
giuliomoro@153 100 void WriteFile::setLineLength(int newLineLength){
giuliomoro@153 101 lineLength=newLineLength;
giuliomoro@153 102 free(buffer);
giuliomoro@159 103 bufferLength = lineLength * (int)1e7; // circular buffer of length 1e7 lineLenghts
giuliomoro@153 104 buffer = (float*)malloc(sizeof(float) * bufferLength);
giuliomoro@153 105 }
giuliomoro@153 106
giuliomoro@153 107 void WriteFile::log(float value){
giuliomoro@157 108 if(fileType != kBinary && (format == NULL || buffer == NULL))
giuliomoro@153 109 return;
giuliomoro@153 110 buffer[writePointer] = value;
giuliomoro@153 111 writePointer++;
giuliomoro@153 112 if(writePointer == bufferLength){
giuliomoro@153 113 writePointer = 0;
giuliomoro@153 114 }
giuliomoro@157 115 if((fileType == kText && writePointer == textReadPointer - 1) ||
giuliomoro@157 116 (fileType == kBinary && writePointer == binaryReadPointer - 1)){
giuliomoro@157 117 fprintf(stderr, "%d %d WriteFile: pointers crossed, you should probably slow down your writing to disk\n", writePointer, binaryReadPointer);
giuliomoro@153 118 }
giuliomoro@153 119 if(threadRunning == false){
giuliomoro@153 120 startThread();
giuliomoro@153 121 }
giuliomoro@153 122 }
giuliomoro@153 123
giuliomoro@153 124 void WriteFile::log(float* array, int length){
giuliomoro@153 125 for(int n = 0; n < length; n++){
giuliomoro@153 126 log(array[n]);
giuliomoro@153 127 }
giuliomoro@153 128 }
giuliomoro@153 129
giuliomoro@153 130 WriteFile::~WriteFile() {
giuliomoro@153 131 free(format);
giuliomoro@153 132 free(buffer);
giuliomoro@153 133 free(header);
giuliomoro@153 134 free(footer);
giuliomoro@153 135 free(stringBuffer);
giuliomoro@153 136 }
giuliomoro@153 137
giuliomoro@153 138 void WriteFile::setFormat(const char* newFormat){
giuliomoro@153 139 allocateAndCopyString(newFormat, &format);
giuliomoro@153 140 for(unsigned int n = 0; n < formatTokens.size(); n++){
giuliomoro@153 141 free(formatTokens[n]);
giuliomoro@153 142 }
giuliomoro@153 143 formatTokens.clear();
giuliomoro@153 144 int tokenStart = 0;
giuliomoro@153 145 bool firstToken = true;
giuliomoro@153 146 for(unsigned int n = 0; n < strlen(format)+1; n++){
giuliomoro@153 147 if(format[n] == '%' && format[n + 1] == '%'){
giuliomoro@153 148 n++;
giuliomoro@153 149 } else if (format[n] == '%' || format[n] == 0){
giuliomoro@153 150 if(firstToken == true){
giuliomoro@153 151 firstToken = false;
giuliomoro@153 152 continue;
giuliomoro@153 153 }
giuliomoro@153 154 char* string;
giuliomoro@153 155 unsigned int tokenLength = n - tokenStart;
giuliomoro@153 156 if(tokenLength == 0)
giuliomoro@153 157 continue;
giuliomoro@153 158 string = (char*)malloc((1+tokenLength)*sizeof(char));
giuliomoro@153 159 for(unsigned int i = 0; i < tokenLength; i++){
giuliomoro@153 160 string[i] = format[tokenStart + i];
giuliomoro@153 161 }
giuliomoro@153 162 string[tokenLength] = 0;
giuliomoro@153 163 formatTokens.push_back(string);
giuliomoro@153 164 tokenStart = n;
giuliomoro@153 165 }
giuliomoro@153 166 }
giuliomoro@153 167 setLineLength(formatTokens.size());
giuliomoro@153 168 }
giuliomoro@153 169
giuliomoro@153 170 int WriteFile::getNumInstances(){
giuliomoro@153 171 return objAddrs.size();
giuliomoro@153 172 }
giuliomoro@153 173
giuliomoro@153 174 void WriteFile::startThread(){
giuliomoro@153 175 BeagleRT_scheduleAuxiliaryTask(writeAllFilesTask);
giuliomoro@153 176 }
giuliomoro@153 177
giuliomoro@153 178 void WriteFile::stopThread(){
giuliomoro@153 179 threadIsExiting=true;
giuliomoro@153 180 }
giuliomoro@153 181
giuliomoro@153 182 bool WriteFile::threadShouldExit(){
giuliomoro@153 183 return(gShouldStop || threadIsExiting);
giuliomoro@153 184 }
giuliomoro@153 185
giuliomoro@153 186 bool WriteFile::isThreadRunning(){
giuliomoro@153 187 return threadRunning;
giuliomoro@153 188 }
giuliomoro@153 189
giuliomoro@153 190 float WriteFile::getBufferStatus(){
giuliomoro@153 191 return 1-getOffset()/(float)bufferLength;
giuliomoro@153 192 }
giuliomoro@153 193
giuliomoro@157 194 int WriteFile::getOffsetFromPointer(int aReadPointer){
giuliomoro@157 195 int offset = writePointer - aReadPointer;
giuliomoro@157 196 if( offset < 0)
giuliomoro@157 197 offset += bufferLength;
giuliomoro@157 198 return offset;
giuliomoro@157 199 }
giuliomoro@153 200 int WriteFile::getOffset(){
giuliomoro@157 201 if(fileType == kBinary){
giuliomoro@157 202 return getOffsetFromPointer(binaryReadPointer);
giuliomoro@157 203 }
giuliomoro@157 204 else{
giuliomoro@157 205 return getOffsetFromPointer(textReadPointer);
giuliomoro@157 206 }
giuliomoro@153 207 }
giuliomoro@153 208
giuliomoro@159 209 void WriteFile::writeOutput(bool flush){
giuliomoro@158 210 while((echo == true || fileType == kText) && getOffsetFromPointer(textReadPointer) >= lineLength){ //if there is less than one line worth of data to write, skip over.
giuliomoro@157 211 // So we make sure we only write full lines
giuliomoro@153 212 writeLine();
giuliomoro@153 213 }
giuliomoro@157 214 if(fileType == kBinary){
giuliomoro@159 215 int numBinaryElementsToWriteAtOnce = 3*(int)1e5;
giuliomoro@157 216 while(getOffsetFromPointer(binaryReadPointer) > numBinaryElementsToWriteAtOnce){
giuliomoro@157 217 int elementsToEndOfBuffer = bufferLength - binaryReadPointer;
giuliomoro@157 218 int numberElementsToWrite = numBinaryElementsToWriteAtOnce < elementsToEndOfBuffer ?
giuliomoro@157 219 numBinaryElementsToWriteAtOnce : elementsToEndOfBuffer;
giuliomoro@157 220 numberElementsToWrite = fwrite(&(buffer[binaryReadPointer]), sizeof(float), numberElementsToWrite, file);
giuliomoro@157 221 binaryReadPointer += numberElementsToWrite;
giuliomoro@157 222 if(binaryReadPointer >= bufferLength){
giuliomoro@157 223 binaryReadPointer = 0;
giuliomoro@157 224 }
giuliomoro@157 225 }
giuliomoro@159 226 if(flush == true){ // flush all the buffer to the file
giuliomoro@157 227 while(getOffsetFromPointer(binaryReadPointer) != 0){
giuliomoro@157 228 binaryReadPointer += fwrite(&(buffer[binaryReadPointer]), sizeof(float), 1, file);
giuliomoro@157 229 if(binaryReadPointer >= bufferLength){
giuliomoro@157 230 binaryReadPointer = 0;
giuliomoro@157 231 }
giuliomoro@157 232 }
giuliomoro@157 233 }
giuliomoro@157 234 }
giuliomoro@153 235 }
giuliomoro@153 236
giuliomoro@159 237 void WriteFile::writeAllOutputs(bool flush){
giuliomoro@153 238 for(unsigned int n = 0; n < objAddrs.size(); n++){
giuliomoro@159 239 objAddrs[n] -> writeOutput(flush);
giuliomoro@153 240 }
giuliomoro@153 241 }
giuliomoro@153 242
giuliomoro@153 243 void WriteFile::writeAllHeaders(){
giuliomoro@153 244 for(unsigned int n = 0; n < objAddrs.size(); n++){
giuliomoro@153 245 objAddrs[n] -> writeHeader();
giuliomoro@153 246 }
giuliomoro@153 247 }
giuliomoro@153 248
giuliomoro@153 249 void WriteFile::writeAllFooters(){
giuliomoro@153 250 for(unsigned int n = 0; n < objAddrs.size(); n++){
giuliomoro@153 251 objAddrs[n] -> writeFooter();
giuliomoro@153 252 }
giuliomoro@153 253 }
giuliomoro@153 254
giuliomoro@153 255 void WriteFile::writeHeader(){
giuliomoro@153 256 print(header);
giuliomoro@153 257 }
giuliomoro@153 258
giuliomoro@153 259 void WriteFile::writeFooter(){
giuliomoro@153 260 print(footer);
giuliomoro@153 261 fflush(file);
giuliomoro@153 262 fclose(file);
giuliomoro@153 263 }
giuliomoro@153 264
giuliomoro@153 265 void WriteFile::setHeader(const char* newHeader){
giuliomoro@153 266 allocateAndCopyString(newHeader, &header);
giuliomoro@153 267 sanitizeString(header);
giuliomoro@153 268 }
giuliomoro@153 269
giuliomoro@153 270 void WriteFile::setFooter(const char* newFooter){
giuliomoro@153 271 allocateAndCopyString(newFooter, &footer);
giuliomoro@153 272 }
giuliomoro@153 273
giuliomoro@153 274 void WriteFile::sanitizeString(char* string){
giuliomoro@153 275 for(int unsigned n = 0; n < strlen(string); n++){ //purge %'s from the string
giuliomoro@153 276 if(string[n] == '%'){
giuliomoro@153 277 string[n] = ' ';
giuliomoro@153 278 }
giuliomoro@153 279 }
giuliomoro@153 280 }
giuliomoro@153 281
giuliomoro@153 282 void WriteFile::run(){
giuliomoro@153 283 threadRunning = true;
giuliomoro@153 284 writeAllHeaders();
giuliomoro@153 285 while(threadShouldExit()==false){
giuliomoro@159 286 writeAllOutputs(false);
giuliomoro@153 287 usleep(sleepTimeMs*1000);
giuliomoro@153 288 }
giuliomoro@159 289 writeAllOutputs(true);
giuliomoro@153 290 writeAllFooters(); // when ctrl-c is pressed, the last line is closed and the file is closed
giuliomoro@153 291 threadRunning = false;
giuliomoro@153 292 }
giuliomoro@153 293
giuliomoro@153 294 void WriteFile::allocateAndCopyString(const char* source, char** destination){
giuliomoro@153 295 free(*destination);
giuliomoro@153 296 *destination = (char*)malloc(sizeof(char) * (strlen(source) + 1));
giuliomoro@153 297 strcpy(*destination, source);
giuliomoro@153 298 }