Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ - How to have multiple threads write to a file

I am currently writing a c++ program that uses threads to write strings to a file. I am using ofstream to write these strings, and I noticed that only one of the threads has access to the file.

So my question: Is there any way to use ofstream in different threads to write to the same file?

If it is possible, any examples would be great. If not, please let me know that as well, and some ways to get around this would be great. I have looked at the following link, except it didn't really make sense to me: Can multiple threads write into a file simultaneously, if all the threads are writing to different locations?

like image 771
Flare Cat Avatar asked Nov 08 '15 17:11

Flare Cat


People also ask

Can two threads write to the same file in C?

So you can have multiple threads accessing the same file, but not via the same FILE* - each thread must have its own, and the file to which they refer must be shareable - which is OS dependent.

Can multiple threads write to the same file?

Different threads should never try to write to the same FITS file. A single process may open the same FITS file with READONLY access multiple times, and thus create multiple 'fitsfile*' pointers to that same file within CFITSIO.

Can you multi thread in C?

Can we write multithreading programs in C? Unlike Java, multithreading is not supported by the language standard. POSIX Threads (or Pthreads) is a POSIX standard for threads. Implementation of pthread is available with gcc compiler.

Can multiple threads write to the same array?

The answer is no. Each array element has a region of memory reserved for it alone within the region attributed the overall array. Modifications of different elements therefore do not write to any of the same memory locations.


1 Answers

One approach is to create a single object that wraps the file and then provide a reference to this wrapper object to all objects that need to write to the file. Within this wrapper class, writing to the file is synchronized so that only one writer can submit data to be written at a time (i.e., one writer will complete before another, or the same writer, can write). For example:

class SynchronizedFile {
public:
    SynchronizedFile (const string& path) : _path(path) {
        // Open file for writing...
    }

    void write (const string& dataToWrite) {
        // Write to the file in a synchronized manner (described below)...
    }

private:
    string _path;
};

class Writer {
public:
    Writer (std::shared_ptr<SynchronizedFile> sf) : _sf(sf) {}

    void someFunctionThatWritesToFile () {
        // Do some work...
        _sf->write("Some data to write...");
    }
private:
    std::shared_ptr<SynchronizedFile> _sf;
};

The client code that uses these writers would resemble the following:

// Create the synchronized file
auto synchronizedFile = std::make_shared<SynchronizedFile>("some/file.txt");

// Create the writers using the same synchronized file
Writer writer1(synchronizedFile);
Writer writer2(synchronizedFile);

Using this approach, a single object (of type SynchronizedFile) manages the file and all writing is managed through this object. Now, in order to ensure that only one thread can use the write(const string&), a std::lock_guard. Using this locking mechanism, the implementation for the SynchronizedFile would resemble:

class SynchronizedFile {
public:
    SynchronizedFile (const string& path) : _path(path) {
        // Open file for writing...
    }

    void write (const string& dataToWrite) {
        // Ensure that only one thread can execute at a time
        std::lock_guard<std::mutex> lock(_writerMutex);

        // Write to the file...
    }

private:
    string _path;
    std::mutex _writerMutex;
};

Since it appears as though writing to a file is not your issue, I have left the opening and writing to you to implement, but the above snippet shows the basic structure for synchronizing the writing. If you have issues opening and writing to the file, let me know and I can flush that out for you.

Note: The above snippets use C++11 structures. If you cannot use C++11, let me know and we can look at using C++98 (or other libraries/APIs) to achieve the same results.

like image 122
Justin Albano Avatar answered Oct 21 '22 22:10

Justin Albano