Created

Embed URL

HTTPS clone URL

SSH clone URL

You can clone with HTTPS or SSH.

Download Gist

This file demonstrates the usage of function try blocks for implementing thread-safe copy constructors. Note, that the equality operator for ExpensiveFoo is omitted (implicitly default), so in reality, there would be even more time spent in the BarSlow copy constructor than in this example.

View func_try_block.cpp
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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
#include <chrono>
#include <iostream>
#include <mutex>
#include <thread>
 
struct ExpensiveFoo
{
ExpensiveFoo()
{
std::cout << "ExpensiveFoo default constructor... ";
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
std::cout << "done.\n";
}
 
ExpensiveFoo(ExpensiveFoo const& other)
{
std::cout << "ExpensiveFoo copy constructor... ";
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::cout << "done.\n";
}
 
~ExpensiveFoo()
{
std::cout << "~ExpensiveFoo\n";
}
 
private:
char data[10000];
};
 
struct BarSlow
{
BarSlow() = default;
BarSlow(const BarSlow& other)
{
std::cout << "BarSlow copy constructor body\n";
std::lock_guard<std::mutex> lock(m);
expensive = other.expensive;
}
 
private:
mutable std::mutex m;
ExpensiveFoo expensive;
};
 
struct BarFast
{
BarFast() = default;
 
BarFast(const BarFast& other)
try
: expensive((other.m.lock(), other.expensive))
{
std::cout << "BarFast copy constructor body\n";
other.m.unlock();
}
catch (...)
{
std::cout << "BarFast copy constructor catch block\n";
other.m.unlock();
}
 
private:
mutable std::mutex m;
ExpensiveFoo expensive;
};
 
void f(BarSlow slow) {}
void f(BarFast fast) {}
 
int main()
{
std::cout << "Starting main.\n";
 
BarSlow slow;
BarFast fast;
 
std::cout << "\n\nMeasuring simple implementation.\n\n";
auto start = std::chrono::system_clock::now();
f(slow);
auto end = std::chrono::system_clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
std::cout << ">>> BarSlow thread-safe copy: " << elapsed.count() << "ms\n";
 
std::cout << "\n\nMeasuring implementation with function try block.\n\n";
start = std::chrono::system_clock::now();
f(fast);
end = std::chrono::system_clock::now();
elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
std::cout << ">>> BarFast thread-safe copy: " << elapsed.count() << "ms\n";
 
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.