I'm trying to make a thread to callback a function of the object that created the thread. But it seems it is not posible to pass "this" as a parameter. Is there a way to implement this? Thanks in advance.
Helper.cpp
void Helper::ProcessSomething(void (*callback)(void))
{
boost::this_thread::sleep(boost::posix_time::seconds(1));
callback();
}
SomeClass.cpp
void SomeClass::Start(void)
{
Helper *helper = Helper();
boost::thread t(&Helper::ProcessSomething, helper, &this->SomeCallback);
t.join();
}
void SomeClass::SomeCallback(void)
{
std::cout << "Callback called" << std::endl;
}
The problem is that SomeCallback is not static (at least not that I can see), so there is another this unaccounted for in thread's constructor. Further, because it's not static, you can't convert SomeCallback to the void(*)(void) that ProcessSomething requires.
The simplest fix would just be to make SomeCallback static (and change &this->SomeCallback to &SomeClass::SomeCallback). But if you can't, this is a possible workaround (I'm assuming you don't have C++11):
void Helper::ProcessSomething(boost::function<void()> callback)
{
boost::this_thread::sleep(boost::posix_time::seconds(1));
callback();
}
// ...
void SomeClass::Start(void)
{
Helper *helper = Helper();
boost::function<void()> callback = boost::bind(&SomeClass::SomeCallback, this);
boost::thread t(&Helper::ProcessSomething, helper, callback);
t.join();
}
If you do have C++11 (but want to use boost::thread anyway), you could use a lambda instead of a binding:
void SomeClass::Start(void)
{
Helper *helper = Helper();
boost::thread t(&Helper::ProcessSomething, helper, [this]() { SomeCallback(); });
t.join();
}
Related
I want to make a Timer class with boost::asio::deadline_timer. I looked into this:
How do I make the boost/asio library repeat a timer?
class DeadlineTimer
{
boost::asio::io_service io;
std::function<void()> fun;
boost::asio::deadline_timer t;
void runTimer()
{
fun();
t.expires_at(t.expires_at() + boost::posix_time::seconds(2));
t.async_wait(boost::bind(&DeadlineTimer::runTimer, this));
}
public:
DeadlineTimer() :t(io, boost::posix_time::seconds(2)){}
void setFunction(std::function<void()> _f)
{
fun = _f;
}
void run()
{
io.run();
}
};
void test()
{
DeadlineTimer timer1;
auto f = []() {
cout << "hello world\n";
};
timer1.setFunction(f);
timer1.run();
}
It allows user to pass a self-defined timer function via timer1.setFunction(f);. Then repeatedly run it (in every 2 second under current circumstance).
But it doesn't work, no output at all.
After some trial-and-error, I’ve managed to update David Wyles’ boost::asio::repeating_timer class to work with Boost >= 1.66 - this neatly encapsulates the functionality of a repeating timer. Online at https://github.com/mikehaben69/boost, including demo source and makefile.
I have a class with a function that takes a std::function and stores it. This part seems to compile ok (but please point out any issue if there are any)
#include <functional>
#include <iostream>
struct worker
{
std::function<bool(std::string)> m_callback;
void do_work(std::function<bool(std::string)> callback)
{
m_callback = std::bind(callback, std::placeholders::_1);
callback("hello world\n");
}
};
// pretty boring class - a cut down of my actual class
struct helper
{
worker the_worker;
bool work_callback(std::string str)
{
std::cout << str << std::endl;
return true;
}
};
int main()
{
helper the_helper;
//the_helper.the_worker.do_work(std::bind(&helper::work_callback, the_helper, std::placeholders::_1)); // <---- SEGFAULT (but works in minimal example)
the_helper.the_worker.do_work(std::bind(&helper::work_callback, &the_helper, std::placeholders::_1)); // <---- SEEMS TO WORK
}
I get a segfault, but I am not sure why. I have used this before, in fact, I copied this example from another place I used it. The only real difference that the member function was part of the class I called it from (i.e. this instead of the_helper).
So this is why I am also asking if there is anything else I am doing wrong in general? Like should I be passing the std::function as:
void do_work(std::function<bool(std::string)>&& callback)
or
void do_work(std::function<bool(std::string)>& callback)
As also noted by #Rakete1111 in comments, the problem probably was in this code:
bool work_callback(std::string str)
{
std::cout << str << std::endl;
}
In C++ if a non-void function does not return a value the result is undefined behavior.
This example will crash with clang but pass with gcc.
If helper::work_callback returns (e.g, true) the code works just fine.
I don't know why your code seg faults because I was spoiled and skipped std::bind straight to lambdas. Since you use C++11 you should really convert your code from std::bind to lambdas:
struct worker
{
std::function<bool(std::string)> m_callback;
void do_work(std::function<bool(std::string)> callback)
{
m_callback = callback;
callback("hello world\n");
}
};
Now with work_callback and calling do_work things need some analysis.
First version:
struct helper
{
worker the_worker;
bool work_callback(std::string)
{
return false;
}
};
int main()
{
helper the_helper;
the_helper.the_worker.do_work([&](std::string s) { return the_helper.work_callback(s); });
}
Now this version works with your toy example. However out in the wild you need to be careful. The lambda passed to do_work and then stored in the_worker captures the_helper by reference. This means that this code is valid only if the helper object passed as reference to the lambda outlives the worker object that stores the m_callback. In your example the worker object is a sub-object of the the helper class so this is true. However if in your real example this is not the case or you cannot prove this, then you need to capture by value.
First attempt to capture by value (does not compile):
struct helper
{
worker the_worker;
bool work_callback(std::string)
{
return false;
}
};
int main()
{
helper the_helper;
the_helper.the_worker.do_work([=](std::string s) { return the_helper.work_callback(s); });
}
This does not compile because the copy of the_helper stored in the lambda object is const by default and as such you cannot call work_callback on it.
A questionable solution if you can't make work_callback const is to make the lambda mutable:
struct helper
{
worker the_worker;
bool work_callback(std::string)
{
return false;
}
};
int main()
{
helper the_helper;
the_helper.the_worker.do_work([=](std::string s) mutable { return the_helper.work_callback(s); });
}
But you need to think if this is what you intended.
What would make more sense is to make work_callback const:
struct helper
{
worker the_worker;
bool work_callback(std::string) const
{
return false;
}
};
int main()
{
helper the_helper;
the_helper.the_worker.do_work([=](std::string s) { return the_helper.work_callback(s); });
}
The reason for getting SEGFAULT has been already mentioned in the comments.
However, I would like to point out that, you need to use neither std::bind nor std::function, here in your given case. Instead, simply having a lambda and a function pointer you can handle what you intend to do.
struct worker
{
typedef bool(*fPtr)(const std::string&); // define fun ptr type
fPtr m_callback;
void do_work(const std::string& str)
{
// define a lambda
m_callback = [](const std::string& str)
{
/* do something with string*/
std::cout << "Call from worker: " << str << "\n";
return true;
};
bool flag = m_callback(str);// just call the lambda here
/* do some other stuff*/
}
};
struct helper
{
worker the_worker;
bool work_callback(const std::string& str)
{
std::cout << "Call from helper: ";
this->the_worker.do_work(str);
return true; ------------------------>// remmeber to keep the promise
}
};
And use case would be:
int main()
{
helper the_helper;
the_helper.work_callback(std::string("hello world"));
// or if you intend to use
the_helper.the_worker.do_work(std::string("hello world"));
return 0;
}
see Output here:
PS: In the above case, if worker does not required m_callback for later cases(i.e, only for do_work()), then you can remove this member, as lambdas can be created and called at same place where it has been declared.
struct worker
{
void do_work(const std::string& str)
{
bool flag = [](const std::string& str)->bool
{
/* do something with string*/
std::cout << "Call from worker: " << str << "\n";
return true;
}(str); -------------------------------------> // function call
/* do other stuff */
}
};
I've read various answer on SO and still didn't understood how I should make an object method to be callable in this case:
Considering:
Class A
{
void generator(void)
{
int i = 1;
while(1)
{
if(i == 1)
{
one(/***/);//Should be a flag
i = 2;
}
else
{
two(/**/);//Should be a flag
i = 1;
}
}
}
template <typename CallbackFunction>
void one(CallbackFunction&& func)
{
}
template <typename CallbackFunction>
void two(CallbackFunction&& func)
{
}
A()
{
std::thread t(&A::generator, this);
t.detach();
}
};
and a simple main file:
void pOne(/**/)
{
std::cout<<"1"<<std::endl;
}
void pTwo(/**/)
{
std::cout<<"2"<<std::endl;
}
A myA;
A.One(pOne);
A.Two(pTwo);
int main(int argc, char** argv)
{
while(1){}
}
Here are where I'm at:
generator() should update a flag, and both one() & two() should poll on that flag & loop forever.
One() (two() also) should have a function pointer as parameters and if necessary other parameters, pOne() should have the same parameters except the function pointer.
So my questions are:
1) Is my understanding correct?
2) Is there a clean way to make generator() to start one() or two() ? (flags, semaphore, mutex, or anything that is a standard way to do it)
3) Assuming that the code was working, is it behaving as I expect ? i.e. printing 1 and 2?
if it matters, I'm on ubuntu
Disclaimer 1: Like everyone else, I'm interpreting the question as:
-> You need an event handler
-> You want callback methods on those events
And the only reason I think that is because I helped you on a i2c handler sequence before.
Also, there are better logic than this, its provided following your stubs "rules".
You mentioned that you are on Ubuntu, so you will be lacking windows event system.
Disclaimer 2:
1- To avoid going to deep I'm going to use a simple way to handle events.
2- Code is untested & provided for logic only
class Handler
{
private:
std::mutex event_one;
event_one.lock();
void stubEventGenerator(void)
{
for(;;)
{
if(!event_one.try_lock())
{
event_one.unlock();
}
sleep(15); //you had a sleep so I added one
}
}
template <typename CallbackFunction>
void One__(CallbackFunction && func)
{
while(1)
{
event_one.lock();
func();
}
}
public:
Handler()
{
std::thread H(&Handler::stubEventGenerator, this);
}
~Handler()
{
//clean threads, etc
//this should really have a quit handler
}
template <typename CallbackFunction>
void One(CallbackFunction && func) //I think you have it right, still I'm not 100% sure
{
std::thread One_thread(&Handler::One__, this, func); //same here
}
};
Some points:
One() as to be a wrapper for the thread calling One__() if you want it to be non-blocking.
mutex can be a simple way to handle events as long as the same event doesn't occur during its previous occurence (you are free to use a better/more suitable tool for your use case, or use boost:: only if necessary)
Prototype of One() & One__() are probably wrong, that's some research for you.
Finally: How it works:
std::mutex.lock() is blocking as long as it can't lock the mutex, thus One__ will wait as long as your event generator won't unlock it.
Once unlock One__ will execute your std::function & wait for the event (mutex) to be raised (unlock) again.
far from a perfect answer, but lack of time, and not being able to put that in a comment made me post it, will edit later
With whatever limited information you provided this code can be made compilable in following manner:
#include <iostream>
#include <thread>
typedef void(*fptr)();
void pOne(/**/)
{
std::cout<<"1"<<std::endl;
}
void pTwo(/**/)
{
std::cout<<"2"<<std::endl;
}
class A
{
public:
void generator(void)
{
int i = 1;
while(1)
{
if(i == 1)
{
fptr func = pOne;
one(func);//Should be a flag
i = 2;
}
else
{
fptr func = pTwo;
two(func);//Should be a flag
i = 1;
}
}
}
template <typename CallbackFunction>
void one(CallbackFunction&& func)
{
func();
}
template <typename CallbackFunction>
void two(CallbackFunction&& func)
{
func();
}
A()
{
std::thread t(&A::generator, this);
t.detach();
}
};
int main()
{
A myA;
while(1)
{
}
return 0;
}
If you want that one and two should accept any type/number of arguments then pass second argument as variadic template.Also I could not understand why you want one and two to be called from main as your generator function is for this purpose only and this generator function is called from thread which is detached in class constructor
i need make new thread in class and use it.
Somethink like:
class Somethink
{
public:
func_to_be_thread();
init_func();
}
Somethink::init_func()
{
std::thread newThread(func_to_be_thread);
}
int main()
{
Somethink ss;
ss.init_func();
}
EDIT:
How to make it correctly? Everythink i wrote returns error becouse idk how to make new thread in class with parameter (function to run) class method. My question is how to do it correctly?
If you need to create a thread with member function you can do the following:
class Something
{
public:
void func_to_be_thread();
void func_to_be_thread_advanced(const char* arg1);
std::thread init_func();
std::thread init_func_with_param(const char *arg1);
}
std::thread Something::init_func()
{
return std::thread(&Something::func_to_be_thread, this);
}
Also you can do it with lambda and parameters:
std::thread init_func_with_param(const char *arg1)
{
return std::thread([=] { func_to_be_thread_advanced(arg1); });
}
which C++ version are you using ? you can use std::thread only starting C++11 .. if you need more help with the syntax, you can check std::thread calling method of class
Start thread with member function
I have an object that runs around a boost::asio::io_service which has some properties. Something like that:
class Foo
{
private:
// Not an int in my real code, but it doesn't really matter.
int m_bar;
boost::asio::io_service& m_io_service;
boost::asio::strand m_bar_strand;
};
m_bar is to be used only from a handler that is called through the strand m_bar_strand. This allows me not to lock from within those handlers.
To set the m_bar property from outside a thread that runs io_service::run() I wrote an asynchronous_setter, like so:
class Foo
{
public:
void async_get_bar(function<void (int)> handler)
{
m_bar_strand.post(bind(&Foo::do_get_bar, this, handler));
}
void async_set_bar(int value, function<void ()> handler)
{
m_bar_strand.post(bind(&Foo::do_set_bar, this, value, handler));
}
private:
void do_get_bar(function<void (int)> handler)
{
// This is only called from within the m_bar_strand, so we are safe.
// Run the handler to notify the caller.
handler(m_bar);
}
void do_set_bar(int value, function<void ()> handler)
{
// This is only called from within the m_bar_strand, so we are safe.
m_bar = value;
// Run the handler to notify the caller.
handler();
}
int m_bar;
boost::asio::io_service& m_io_service;
boost::asio::strand m_bar_strand;
};
This works perfectly but now I'd like to write a synchronous version of set_bar that sets the value and returns only when the set was effective. It must still guarantee that the effective set will occur within the m_bar_strand. Ideally, something reentrant.
I can imagine solutions with semaphores that would be modified from within the handler but everything I come up seems hackish and really not elegant. Is there something in Boost/Boost Asio that allows such a thing?
How would you proceed to implement this method?
If you need to synchronously wait on a value to be set, then Boost.Thread's futures may provide an elegant solution:
The futures library provides a means of handling synchronous future values, whether those values are generated by another thread, or on a single thread in response to external stimuli, or on-demand.
In short, a boost::promise is created and allows for a value to be set on it. The value can later be retrieved via an associated boost::future. Here is a basic example:
boost::promise<int> promise;
boost::unique_future<int> future = promise.get_future();
// start asynchronous operation that will invoke future.set_value(42)
...
assert(future.get() == 42); // blocks until future has been set.
Two other notable benefits to this approach:
future is part of C++11.
Exceptions can even be passed to future via promise::set_exception(), supporting an elegant way to provide exceptions or errors to the caller.
Here is a complete example based on the original code:
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
class Foo
{
public:
Foo(boost::asio::io_service& io_service)
: m_io_service(io_service),
m_bar_strand(io_service)
{}
public:
void async_get_bar(boost::function<void(int)> handler)
{
m_bar_strand.post(bind(&Foo::do_get_bar, this, handler));
}
void async_set_bar(int value, boost::function<void()> handler)
{
m_bar_strand.post(bind(&Foo::do_set_bar, this, value, handler));
}
int bar()
{
typedef boost::promise<int> promise_type;
promise_type promise;
// Pass the handler to async operation that will set the promise.
void (promise_type::*setter)(const int&) = &promise_type::set_value;
async_get_bar(boost::bind(setter, &promise, _1));
// Synchronously wait for promise to be fulfilled.
return promise.get_future().get();
}
void bar(int value)
{
typedef boost::promise<void> promise_type;
promise_type promise;
// Pass the handler to async operation that will set the promise.
async_set_bar(value, boost::bind(&promise_type::set_value, &promise));
// Synchronously wait for the future to finish.
promise.get_future().wait();
}
private:
void do_get_bar(boost::function<void(int)> handler)
{
// This is only called from within the m_bar_strand, so we are safe.
// Run the handler to notify the caller.
handler(m_bar);
}
void do_set_bar(int value, boost::function<void()> handler)
{
// This is only called from within the m_bar_strand, so we are safe.
m_bar = value;
// Run the handler to notify the caller.
handler();
}
int m_bar;
boost::asio::io_service& m_io_service;
boost::asio::strand m_bar_strand;
};
int main()
{
boost::asio::io_service io_service;
boost::asio::io_service::work work(io_service);
boost::thread t(
boost::bind(&boost::asio::io_service::run, boost::ref(io_service)));
Foo foo(io_service);
foo.bar(21);
std::cout << "foo.bar is " << foo.bar() << std::endl;
foo.bar(2 * foo.bar());
std::cout << "foo.bar is " << foo.bar() << std::endl;
io_service.stop();
t.join();
}
which provides the following output:
foo.bar is 21
foo.bar is 42
You could use a pipe to notify the synchronous method when the value is set in async_set_bar(). Warning, the below code is brain-compiled and likely has errors but it should get the point across
#include <boost/asio.hpp>
#include <iostream>
#include <thread>
class Foo
{
public:
Foo( boost::asio::io_service& io_service ) :
_bar( 0 ),
_io_service( io_service ),
_strand( _io_service ),
_readPipe( _io_service ),
_writePipe( _io_service )
{
boost::asio::local::connect_pair( _readPipe, _writePipe );
}
void set_async( int v ) {
_strand.post( [=]
{
_bar = v;
std::cout << "sending " << _bar << std::endl;
_writePipe.send( boost::asio::buffer( &_bar, sizeof(_bar) ) );
}
);
}
void set_sync( int v ) {
this->set_async( v );
int value;
_readPipe.receive( boost::asio::buffer(&value, sizeof(value) ) );
std::cout << "set value to " << value << std::endl;
}
private:
int _bar;
boost::asio::io_service& _io_service;
boost::asio::io_service::strand _strand;
boost::asio::local::stream_protocol::socket _readPipe;
boost::asio::local::stream_protocol::socket _writePipe;
};
int
main()
{
boost::asio::io_service io_service;
boost::asio::io_service::work w(io_service);
std::thread t( [&]{ io_service.run(); } );
Foo f( io_service );
f.set_sync( 20 );
io_service.stop();
t.join();
}
if you are unable to use c++11 lambdas, replace them with boost::bind and some more completion handler methods.
This is what I came up with:
class synchronizer_base
{
protected:
synchronizer_base() :
m_has_result(false),
m_lock(m_mutex)
{
}
void wait()
{
while (!m_has_result)
{
m_condition.wait(m_lock);
}
}
void notify_result()
{
m_has_result = true;
m_condition.notify_all();
}
private:
boost::atomic<bool> m_has_result;
boost::mutex m_mutex;
boost::unique_lock<boost::mutex> m_lock;
boost::condition_variable m_condition;
};
template <typename ResultType = void>
class synchronizer : public synchronizer_base
{
public:
void operator()(const ResultType& result)
{
m_result = result;
notify_result();
}
ResultType wait_result()
{
wait();
return m_result;
}
private:
ResultType m_result;
};
template <>
class synchronizer<void> : public synchronizer_base
{
public:
void operator()()
{
notify_result();
}
void wait_result()
{
wait();
}
};
And I can use it, that way:
class Foo
{
public:
void async_get_bar(function<void (int)> handler)
{
m_bar_strand.post(bind(&Foo::do_get_bar, this, value, handler));
}
void async_set_bar(int value, function<void ()> handler)
{
m_bar_strand.post(bind(&Foo::do_set_bar, this, value, handler));
}
int get_bar()
{
synchronizer<int> sync;
async_get_bar(boost::ref(sync));
return sync.wait_result();
}
void set_bar(int value)
{
synchronizer<void> sync;
async_set_bar(value, boost::ref(sync));
sync.wait_result();
}
};
The boost::ref is necessary because the instances of synchronizer are non-copyable. This could be avoided by wrapping synchronizer in some other container-class, but I'm fine with that solution as it is.
Note: Do NOT call such "synchronized" functions from inside a handler or it might just deadlock !