std::filesystem
is generally thread-safe for individual operations, meaning that multiple threads can safely perform filesystem operations simultaneously.
However, the standard does not guarantee atomicity or synchronization for compound operations, such as checking for a file's existence and then creating it if it doesn't exist.
This can lead to race conditions in certain scenarios. Here’s an example demonstrating basic thread safety in std::filesystem
:
#include <filesystem>
#include <fstream>
#include <iostream>
#include <mutex>
#include <thread>
namespace fs = std::filesystem;
std::mutex mtx;
void create_file(const fs::path &file_path) {
std::lock_guard<std::mutex> lock(mtx);
std::ofstream file(file_path);
if (file) {
std::cout << "Created file: "
<< file_path.string() << '\n';
} else {
std::cerr << "Failed to create file: "
<< file_path.string() << '\n';
}
}
int main() {
fs::path file1{R"(c:\test\file1.txt)"};
fs::path file2{R"(c:\test\file2.txt)"};
std::thread t1(create_file, file1);
std::thread t2(create_file, file2);
t1.join();
t2.join();
}
Created file: c:\test\file1.txt
Created file: c:\test\file2.txt
In this example:
file1
and file2
as the paths to the files we want to create.create_file
function to create a file.While individual filesystem operations are thread-safe, be cautious with compound operations. For example, if you need to check for the existence of a file and create it if it doesn't exist, you should use proper synchronization mechanisms like mutexes to avoid race conditions:
#include <filesystem>
#include <fstream>
#include <iostream>
#include <mutex>
#include <thread>
namespace fs = std::filesystem;
std::mutex mtx;
void create_file_if_not_exists(
const fs::path &file_path) {
std::lock_guard<std::mutex> lock(mtx);
if (!fs::exists(file_path)) {
std::ofstream file(file_path);
if (file) {
std::cout << "Created file: "
<< file_path.string() << '\n';
} else {
std::cerr << "Failed to create file: "
<< file_path.string() << '\n';
}
} else {
std::cout << "File already exists: "
<< file_path.string() << '\n';
}
}
int main() {
fs::path file{R"(c:\test\file.txt)"};
std::thread t1(create_file_if_not_exists, file);
std::thread t2(create_file_if_not_exists, file);
t1.join();
t2.join();
}
Created file: c:\test\file.txt
File already exists: c:\test\file.txt
In this example:
std::mutex
to synchronize access to the file creation code.std::lock_guard
ensures that only one thread can check for the file’s existence and create it at a time.This synchronization prevents race conditions and ensures that the file is created only once, even if multiple threads attempt to create it simultaneously.
In summary, while std::filesystem
operations are thread-safe, always use synchronization mechanisms for compound operations to ensure proper behavior in a multi-threaded environment.
Answers to questions are automatically generated and may not have been reviewed.
Create, delete, move, and navigate through directories and files using the standard library's filesystem
module.