0

So based on this scenario:

#include <fstream>
#include <thread>
#include <string>

// Atomize this
std::ofstream f;

void func() 
{
  std::queue<std::string> sq;
  std::string s;
  for (volatile int i = 0; i < 10 || !f.eof(); i++) {
    // Will s get corrupted?
    std::getline(f, s);
    sq.push(s);
  }
}

int main()
{
  f.open("somefile.txt");
  std::vector<std::thread> threads;
  for (int i = 0; i < 10; i++) {
    threads.push_back(std::thread(func));
  }
}

I'll be calling getline inside of a thread, which (I assume) works no different than a loop that increments the file pointer into a string until a delimiter. What is the appropriate way of securing the file pointer such that getline doesnt collect garbage data. Point B: I just set up a mutex to lock it while getline is being run.

I read that atomic type variables cannot be written/read at the same time, but I'm unsure if this works in a member function as well. Does it lock from reading/writing until the getline method terminates? Or will it (un)lock as getline loops *f;

Of course I can mutex this, I am just curious if streams are threadsafe in this scenario.

phinite
  • 1
  • 3
  • 1
    Side note: You should verify that `std::getline` succeeded before using its result. See the following question for further information: [Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?](https://stackoverflow.com/q/5605125/12149471) – Andreas Wenzel Feb 04 '22 at 07:07
  • 2
    Yes you need some kind of locking for the `getline` call. A mutex and a lock is the typical solution. You can't make only the stream atomic, there's to many layers of abstraction in the C++ stream I/O library, it's hard to make all the layers atomic. – Some programmer dude Feb 04 '22 at 07:10
  • Also note that even if you add locking for the `getline` call, it only protects against the data-race. There's no synchronization between the threads, and no control over which threads will read which lines. – Some programmer dude Feb 04 '22 at 07:11
  • FYI: [In C++, are fstream objects thread safe?](https://www.quora.com/In-C-are-fstream-objects-thread-safe) (...by Jerry Coffin on quora. I ask myself whether this is [Jerry Coffin](https://stackoverflow.com/users/179910/jerry-coffin).) – Scheff's Cat Feb 04 '22 at 07:15
  • This looks like a bad idea. What problem are you trying to solve? – zdf Feb 04 '22 at 07:20

1 Answers1

0

Using stream objects in multiple threads without explicit synchronization generally introduces data races. (The standard streams std::cout and companions are an exception under certain conditions.)

If by "atomize" you mean something like

std::atomic<std::ofstream> f;

that is not possible. std::atomic works only with trivially copyable types (or std::shared_ptr/std::weak_ptr).

You need to use a mutex.

user17732522
  • 53,019
  • 2
  • 56
  • 105