Skip to content

Instantly share code, notes, and snippets.

@sztomi
Created May 7, 2014 14:17
Show Gist options
  • Save sztomi/48b3e44aee77c71b552b to your computer and use it in GitHub Desktop.
Save sztomi/48b3e44aee77c71b552b to your computer and use it in GitHub Desktop.
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.
#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