C++: We make any object thread-safe
Introduction:
Smart pointer that makes any object thread-safe for any operations, with the performance equal to that of optimized lock-free containers.
In these 3 articles I’ll tell in detail about atomic operations, memory barriers and the rapid exchange of data between threads, as well as about the “sequence-points” by the example of “execute-around-idiom”. At the same time, we will try to do something useful together.
There are no thread-safe containers (array, list, map ...) in the standard C++ library, which could be used in multiple threads without additional locks. In case of usage of standard containers for multithreading exchange, there is a danger for you to forget to protect one of the code sections with mutex or by mistake to protect it with another mutex.
Obviously, a developer will make more mistakes if he/she uses his/her own solution instead of a standard one. And if the task is so complex that there is no any standard solution, then the developer, while trying to find a solution, will be awash with errors.
Relying on the “practicality beats purity” principle, we will try to create not an ideal, but a practical solution to this problem.
In this article, we will realize a smart pointer that makes any object thread-safe, with the performance equal to that of optimized lock-free containers.
A simplified, non-optimized example of using such a pointer:
int main() {
contfree_safe_ptr< std::map< std::string, int > > safe_map_string_int;
std::thread t1([&]() { safe_map_string_int->emplace("apple", 1); });
std::thread t2([&]() { safe_map_string_int->emplace("potato", 2); });
t1.join(); t2.join();
std::cout << "apple = " << (*safe_map_string_int)["apple"] <<
", potato = " << (*safe_map_string_int)["potato"] << std::endl;
return 0;
}
We will cite a quotations from the standard, which guarantees the necessary behavior, for each step of our algorithm.
We will consider C++ memory model, as well as different possible versions of synchronization and data exchange between threads, in detail.
In this article, we will develop a thread-safe pointer
safe_ptr<>
. In the second article, we will realize an optimized “contention-free shared-mutex” and an optimized pointer contfree_safe_ptr<>
on its basis. And in the third article, we will show examples of optimal utilization of contfree_safe_ptr<>
and provide performance tests, and we will compare it with highly optimized lock-free containers.
Three related articles:
1. We make any object thread-safe - this article
2. We make a std::shared_mutex 10 times faster
3. Thread-safe std::map with the speed of lock-free map
Comments
Post a Comment