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.
Comprehensive course covering advanced concepts, and how to use them on large-scale projects.
View Course