1

As an exercise I want to write a class which describes a file containing blocks of data. Inside the destructor of the class I simply called close, since (quoting from http://www.cplusplus.com/doc/tutorial/files/)

When the buffer is flushed, all the data contained in it is written to the physical medium (if it is an output stream). This process is called synchronization and takes place under any of the following circumstances: When the file is closed: before closing a file, all buffers that have not yet been flushed are synchronized and all pending data is written or read to the physical medium.

A sample code is given below.

#pragma once
#include <filesystem>
#include <fstream>
#include <string>

namespace fs = std::filesystem;

template<class Block>
class BlockFile {
  
private:

  fs::path mFilePath;
  std::fstream mFile;
  
public:

  BlockFile(fs::path fPath) : mFilePath{fPath}
  {
    // this is so wrong for so many reasons (file might exist, not thread safe etc.) but anyway
    auto touch = ofstream{mFilePath};
  }

  ~BlockFile() {
    mFile.close();
  }  

// read, write, append methods etc..

};

However, when I read another solution, the destructor was actually implemented as

~BlockFile() 
{
  mFile.flush();
  mFile.sync();
  mFile.close();
}

My main question is why do we need to explicitly flush and sync, since the quote above says that it is done before the file is closed?

Extra question: In the accepted answer of this question What is the difference between flush() and sync() in regard to fstream buffers? it is mentioned

basic_ostream::flush This is a non-virtual function which writes uncommited changes to the underlying buffer. In case of error, it sets an error flag in the used stream object. This is because the return value is a reference to the stream itself, to allow chaining.

basic_filebuf::sync This is a virtual function which writes all pending changes to the underlying file and returns an error code to signal success or failure.

What is the difference between uncommitted changes and pending changes?

AngelosFr
  • 115
  • 1
  • 9
  • In the class in the question there is no need whatsoever for either of those destructors. The compiler-generated destructor will work just fine; it calls the destructor for `mFile`, which takes care of all that flushing and closing. – Pete Becker Jan 07 '22 at 14:47

1 Answers1

1

My main question is why do we need to explicitly flush and sync, since the quote above says that it is done before the file is closed?

You don't. Not all code found on the internet is of highest quality. :-)

  ~BlockFile() {
    mFile.close();
  }  

This is not really necessary either, as the fstream destructor also calls close if the file is still open.

The "only" reason to call close is to check its return value, which indicates if it was successful or not. Perhaps flushing the buffers caused a disk full? Or writing to a network store failed because the connection was lost?

What is the difference between uncommitted changes and pending changes?

Not much, I think they are just synonyms here.

BoP
  • 2,310
  • 1
  • 15
  • 24