Since the C++11 standard, the Concurrency Support Library includes built-in support for threads (std::thread
) with atomic operations (std::atomic
). C++11 provides both weak and strong compare-and-exchange operations in multi-threading applications. Since C++11, strong compare and exchange are used in modern C++ standards such as C++14, C++17, C++20, and in other new standards. In this post, we explain what is strong compare and exchange is with simple examples.
What is strong compare and exchange in C++?
The Strong Compare and Exchange template atomically compares the value pointed to by the atomic object with the value pointed to by expected. This feature comes with C++11 and is used in other modern C++ standards, and performs the following operations based on the comparison results:
- If the comparison result is true (bitwise-equal), the function replaces the value pointed to by the atomic object with the value desired.
- If the comparison result is false, the function updates the value in expected with the value pointed by the atomic object.
There are two most common syntaxes, here is the syntax for the compare_exchange_strong
, first,
1 2 3 |
bool compare_exchange_strong( T& expected, T desired) noexcept; |
and in strong compare and exchange atomic operations, we can use std::compare_exchange_strong
template with memory order types. Here is the syntax for the compare_exchange_strong
with memory orders,
1 2 3 4 5 |
bool compare_exchange_strong( T& expected, T desired, std::memory_order success, std::memory_order failure ) noexcept; |
here is how we can use it,
1 2 3 4 5 6 7 |
std::atomic<int> x; exchanged = x.compare_exchange_strong( expected, desired); exchanged = x.compare_exchange_strong( expected, desired, std::memory_order_release, std::memory_order_relaxed); |
Note that providing both compare_exchange_strong
and compare_exchange_weak
allows us to decide whether we want the library to handle spurious failures (using compare_exchange_strong
) or if we want to handle it in ourr own code (using compare_exchange_weak
). The compare_exchange_strong
needs extra overhead to retry in the case of failure. For details, please see Load-link/store-conditional in Wikipedia.
Is there a simple example of strong compare and exchange in C++?
Here is a simple example about strong compare and exchange in modern C++.
Let’s assume we have a thread function myf1()
that ensures value is changed after a strong compare and exchange. This is how we can do this,
1 2 3 4 5 6 7 8 9 10 11 12 13 |
void myf1(int desired) { int expected = 1; bool exchanged; do { exchanged = x.compare_exchange_strong( expected, desired ); std::cout << x.load() << ","; }while (!exchanged); } |
Is there a full example about strong compare and exchange in C++?
Let’s assume we have a thread function myf1()
that ensures value is changed after a strong compare and exchange. Let’s do the change after 1 second with myf2()
. Here is the full example of strong compare and exchange in modern C++,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
#include <iostream> #include <atomic> #include <thread> std::atomic<int> x = 0; void myf1(int desired) { int expected = 1; bool exchanged; do { exchanged = x.compare_exchange_strong( expected, desired ); std::cout << x.load() << ","; }while (!exchanged); std::cout << " myf1 done, "; } void myf2() { std::this_thread::sleep_for(std::chrono::milliseconds(1000)); x.store(5); } int main() { std::cout << "x= "; std::thread t1 (myf1, 7); std::thread t2 (myf2); t1.join(); t2.join(); std::cout << "x= " << x.load() << std::endl; system("pause"); return 0; } |
The output will be as follows.
1 2 3 4 |
x= 0,7, myf1 done, x= 5 Press any key to continue . . . |
As you see strong compare-and-exchange operation is an atomic operation that can be used in multi-threaded applications to achieve synchronization. For more information about this strong compare and exchange feature, see Strong Compare and Exchange Proposal document.
C++ Builder is the easiest and fastest C and C++ IDE for building simple or professional applications on the Windows, MacOS, iOS & Android operating systems. It is also easy for beginners to learn with its wide range of samples, tutorials, help files, and LSP support for code. RAD Studio’s C++ Builder version comes with the award-winning VCL framework for high-performance native Windows apps and the powerful FireMonkey (FMX) framework for cross-platform UIs.
There is a free C++ Builder Community Edition for students, beginners, and startups; it can be downloaded from here. For professional developers, there are Professional, Architect, or Enterprise version.
Design. Code. Compile. Deploy.
Start Free Trial
Free C++Builder Community Edition