I'm trying to make a class runner (run a class at a fixed time freq), which runs a class in another thread, and can be controlled (like pause, resume, stop) from main thread.
So I want to take advantage of C++11's Functor and other features. But I have a strange problem, the Functor's destructor passed into Runner has been called twice.
#include <iostream>
#include <chrono>
#include <thread>
using namespace std;
class Runner {
public:
typedef function<bool()> fn_t;
Runner(fn_t &&fn) : fn_(move(fn)), thread_(Thread, ref(*this)) {
cout << "Runner" << endl;
}
~Runner() {
cout << "~Runner" << endl;
thread_.join();
}
private:
fn_t fn_;
thread thread_;
static void Thread(Runner &runner) {
while (runner.fn_()) {
cout << "Running" << endl;
this_thread::sleep_for(chrono::milliumseconds(1));
}
}
};
class Fn {
public:
Fn() : count(0) {
cout << "Fn" << endl;
}
~Fn() {
cout << "~Fn" << endl;
}
bool operator()() {
return (++count < 5);
}
private:
int count;
};
int main (int argc, char const* argv[])
{
Fn fn;
Runner runner(move(fn));
return 0;
}
outpus:
Fn
Runner
~Fn
~Runner
Running
Running
Running
Running
Running
~Fn
~Fn
and if I change
Fn fn;
Runner runner(move(fn));
to
Runner runner(Fn());
the program outpus nothing and stalls. I have tried to disable compiling optimization, nothing changes. Any explanation?
How can I fix this or do the samething in other method? Should I implement this class like std::async / std::thread?
Update to Runner runner(Fn())
This statement was interrupted as a function declaration.
Runner runner((Fn()))
solved problem.
Thanks for all comments and answers. After look into rvalue, seems I have misunderstand the meaning of rvalue reference from ground 0. I will try some other ways.
Final Solution for this problem
#include <iostream>
#include <chrono>
#include <thread>
#include <vector>
using namespace std;
template<typename T, typename... Args>
class Runner {
public:
Runner(Args&&... args) :
t(forward<Args>(args)...),
thread_(Thread, ref(*this)) {
cout << "Runner" << endl;
}
~Runner() {
cout << "~Runner" << endl;
thread_.join();
}
private:
T t;
thread thread_;
static void Thread(Runner &runner) {
while (runner.t()) {
cout << "Running" << endl;
this_thread::sleep_for(chrono::milliseconds(100));
}
}
};
class Fn {
public:
Fn() : count(0) {
cout << "Fn" << endl;
}
~Fn() {
cout << "~Fn" << endl;
}
bool operator()() {
return (count++ < 5);
}
private:
int count;
};
int main (int argc, char const* argv[])
{
//vector<Fn> fns;
//fns.emplace_back(Fn());
Runner<Fn> runner;
return 0;
}
outpus:
Fn
Runner
~Runner
Running
Running
Running
Running
Running
~Fn