Home > Back-end >  Automatic callback to close fstream contained in file logger class
Automatic callback to close fstream contained in file logger class

Time:12-23

To log different values in different parts of my c application I want to be able to instantiate a class that abstracts all the required commands for logging different values in a file. This is a prototype header of the class:

#include <string.h>
#include <fstream>
#include <iostream>

#include <Eigen/Dense>

....

class FileLogger {
 public:
  FileLogger(const std::string& log_name, const std::string& columnNames, const uint& columnCount, const double& timerOffsetSeconds = 0);

  // Checks if logging of previous timestamp is completed and 
  //starts a new row with logging the current time. 
  void startNewTimestamp();

  // different predefined methods to log several data types
  void logScalar(const double& value);
  void logVector(const Eigen::VectorXd& values);

  template <int SIZE, typename TYPE>
  void logArray(TYPE (&values)[SIZE]) {
    for (int i; i < SIZE; i  ) {
      fileHandle_ << values[i] << ",";
      currentColumnCount_  = 1;
    }
  }

  // Method to close the fileHandle_ of the class
  void closeFileHandle();

 private:
  void checkLastTimestampCompletion();
  uint countColumnNames();

  std::string file_name_;
  uint currentColumnCount_;
  const uint columnCount_;
  const std::string columnNames_;

  std::ofstream fileHandle_;

  ....
};

The problem that i now experience, is that each class needs to close it's fileHandle_ using the method closeFileHandle() before the program is terminated in order to obtain a working log. Since the program is usually terminated using CTL C this needs to happen in a signal callback. I have found out that a termination signal can be used to execute a callback function as follows:

...
#include <signal.h>
#include <iostream>

void signal_callback_handler(int signum) {
  std::cout << "Caught signal " << signum << ", starting exit procedure." << std::endl;
  .... do something ...
  exit(1);
}

int main(){
  .... 
  signal(SIGINT, signal_callback_handler);
  ....
}

The only way I could find to close all the required fileHandle_ of each instance of FileLogger class was to define them globally and to manually add fileLogger.closeFileHandle(); to the callback function. This is undesirable for multiple reasons.

Therefore, I wondered if there is a way to somehow contain that functionality of closing the file handle upon exiting the program in the class itself in a way that the class can just be instantiated anywhere in the code? Or if that is not possible how could I handle the problem in another way?

CodePudding user response:

The destruction of each FileLogger solves this automatically since fileHandle_ will be closed when the FileLogger either goes out of scope or when you call std::exit.

  • Related