Skip to content

Instantly share code, notes, and snippets.

@eruffaldi
Last active September 29, 2015 19:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eruffaldi/b3c65c431577d20f475d to your computer and use it in GitHub Desktop.
Save eruffaldi/b3c65c431577d20f475d to your computer and use it in GitHub Desktop.
Execution of a C++ code block only one (C++11)
#include <mutex>
#include <condition_variable>
#include <functional>
#include <iostream>
#include <thread>
#include <chrono>
class OnceHard
{
public:
OnceHard(std::function<void()> x) : action(x) {}
bool operator()()
{
std::unique_lock<std::mutex> lk(mtx);
if(!done)
{
action();
done = true;
return true;
}
else
return false;
}
private:
bool done = false;
std::function<void()> action;
std::mutex mtx;
};
class Once
{
public:
// inited before threads spawn
Once(std::function<void()> x) : action(x) {}
bool operator()()
{
std::unique_lock<std::mutex> lk(mtx);
if(state == State::Not)
{
state = State::Doing;
lk.unlock(); // momentarly release
action(); // run once
lk.lock(); // lock again
state = State::Done;
cv.notify_all();
return true;
}
else
{
std::cerr << "waitcomplete\n";
cv.wait(lk, [this]{return this->state == State::Done;});
std::cerr << "waitdone\n";
return false;
}
}
private:
enum class State { Not, Doing, Done};
State state = State::Not;
std::function<void()> action;
std::mutex mtx;
std::condition_variable cv;
};
int main(int argc, char * argv[])
{
OnceHard once([] () {
std::cerr << "oncestart\n";
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cerr << "onceend\n";
});
std::function<void()> waits = [&] ()
{
std::cout << "got " << once() << std::endl;
};
std::thread t1(waits), t2(waits), t3(waits);
t1.join();
t2.join();
t3.join();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment