8

I am working on a program, which uses multiple std::ifstreams for reading a binary file, one std::ifstream for each thread. Now I need to know, if std::ofstream is thread-safe on Windows and Linux for writing in a same file. I am using using only one std::ofstream and using for multiple threads.
I am reading different blocks using using each thread and writing those block in output file using seekp() and write(). Currently it is working for me but whether it is problematic for big files.

Is std::ofstream thread safe?

Kiril Kirov
  • 37,467
  • 22
  • 115
  • 187
Dipak
  • 123
  • 1
  • 1
  • 10
  • 1
    Please see the following it will be helpful Please go through this http://stackoverflow.com/questions/2754303/is-stdifstream-thread-safe-lock-free – VDN Nov 26 '13 at 08:41
  • 2
    *iostream* classes are an exception. It is safe to write to an object from multiple threads.If you don't mind that "this can result in the output from the two threads being intermixed." – SChepurin Nov 26 '13 at 09:28
  • Also see [How to easily make std::cout thread-safe?](http://stackoverflow.com/q/14718124/1468366) – MvG Feb 25 '14 at 07:37

4 Answers4

11

If I haven't misunderstood you - no, nothing in the standard library is thread safe (except the std::thread specific things, of course (from C++11 and later)). You need additional synchronization.

Even more - if there are several processes, reading from/writing to these files, you need to lock the files, to sync the access.

Kiril Kirov
  • 37,467
  • 22
  • 115
  • 187
10

From C++ standards (Input/Output Library Thread Safety):

27.1.3 Thread safety [iostreams.thread-safety]

Concurrent access to a stream object [string.streams, file.streams], stream buffer object [stream.buffers], or C Library stream [c.files] by multiple threads may result in a data race [intro.multithread] unless otherwise specified [iostream.objects]. [Note: Data races result in undefined behavior [intro.multithread].

MvG
  • 57,380
  • 22
  • 148
  • 276
Claudi
  • 5,224
  • 17
  • 30
2

I have written a little program to verify the thread-safety of std::ifstream and std::ofstream https://github.com/rmspacefish/rpi-file-concurrency . I have tested with on a Linux Desktop host and a Raspberry Pi. The program starts two threads, one writer thread and one reader thread and there is a textual mode and a binary mode.

In the textual mode, I am writing two lines in the writer thread, and the reader thread attempts to read two lines. For the textual mode, I get the following output:

Concurrent file access test
Write Open Fail Count: 0
Write Count: 191090
Write Fail Count: 0

Read Open Fail Count: 0
Read Count: 93253
Read One Line Count: 93253
Read Both Lines Count: 93253
Faulty Read Count: 0
EOF Count: 0
Fail Count: 0

Finished.

So this appears to be thread-safe for Linux. For the binary mode, I am writing a binary block in form of a struct consisting of multiple fields like char arrays, integers with various sizes etc. I have two states which are written in alternating cycles. In the reader thread, I check the consistency of the data (inconistent states or worse, wrong values). Here I get the following results

Concurrent file access test
Write Open Fail Count: 0
Write Count: 0
Write Fail Count: 0

Read Open Fail Count: 0
Read Count: 0
Blob in state one read: 25491
Blob in state two read: 24702
Blob in invalid state: 0
Faulty Read Count: 0
EOF Count: 91295
Fail Count: 91295

Finished.

I checked the error flags after calling read (and this is important). If there are no error flags, the state is read in a consistent manner. It looks thread-safe to me.

The thread-safety might still be implementation dependent, but at least for Linux/GCC, file access seems to be thread-safe. I will still test this with MSVC on Windows, but Microsoft specified this should be thread-safe as well.

Spacefish
  • 305
  • 4
  • 11
0

Yes. It is.

For Windows: it is safe to write to fstream from multiple threads on windows. Please see the msdn document: Thread Safety in the C++ Standard Library

For Linux: In short, it is. From the document of libstdc++: "if your platform's C library is threadsafe, then your fstream I/O operations will be threadsafe at the lowest level". Is your platform's C library threadsafe? Yes. The POSIX standard requires that C stdio FILE* operations(such as fread/fwrite) are atomic, and glibc did so.

Changming Sun
  • 857
  • 2
  • 7
  • 19
  • 2
    I'm using OpenMP to compute and output to the same `ofstream` from multiple threads. Unless I protect the output (`ofstream << "Result: " << value << endl`) with `#pragma omp critical`, _sometimes_ I get the lines garbled. Not often, but it happens... This is on RHEL6, with hand-built g++-8.1 and its own libstdc++ – Mikhail T. Aug 01 '18 at 22:11
  • 2
    If you change your code to: std::ostringstream oss; oss << "Result: " << value << "\n"; ofstream<< oss.str(); That would be fine. – Changming Sun Aug 02 '18 at 23:07
  • 2
    Whether that works or not, the asker’s question was: “is `ofstream` thread-safe?”. Not “how do I deal with it being unsafe?” – Mikhail T. Aug 03 '18 at 12:30
  • Well, maybe I was wrong. I just found, on Linux ,at syscall level, it can't write more than 2GB bytes in a single call. So, if glibc has an internal lock around the file descriptor for this, then it should be fine. But I don't know the details. Will update this answer later. – Changming Sun Feb 27 '19 at 23:19
  • 1
    Well, I cannot follow your answer: The microsoft document, that you linked to, guarantees thread safety only for writing to the standard iostream objects `cin`, `cout`, `cerr`, `clog`, `wcin`, `wcout`, `wcerr` and `wclog`. So writing to any other `std::ofstream` is generally NOT thread safe. In particular, the document even further warns, that reading from a stream buffer is actually considered an [unsafe] write, as the buffer position is updated. – Kai Petzke Sep 30 '19 at 12:27
  • Sorry but "*It is safe in Windows and GCC*" != "*Yes. It is*". Good to know though. – rustyx Jun 02 '20 at 20:30