I'm working a project here trying to port some Linux C++ code to be cross platform, and I have here a wrapper thread class that's using pthread.
#include <pthread.h>
class ServerThread {
public:
pthread_t tid;
pthread_mutex_t mutex;
int Create (void* callback, void* args);
};
I'm trying to port this directly to std::thread but the Create method here uses pthread_create which I understand starts the thread, but I'm unable to find the std equivalent.
int ServerThread :: Create (void* callback, void* args) {
int tret = 0;
tret = pthread_create(&this->tid, nullptr, (void*(*)(void *)) callback, args);
if (tret != 0) {
std::cerr << "Error creating thread." << std::endl;
return tret;
}
return 0;
}
I genuinely don't understand what I'm looking at with that pthread_create function call. Is that some kind of strange void pointer double cast?
I have no documentation with the code base I'm working with, so my guess is as good as the next guys'.
std::thread's constructor will start the new thread with the function and arguments provided.
So roughly:
void thread_func(int, double) {
}
class ServerThread {
std::thread thr;
ServerThread(int arg1, double arg2)
: thr(thread_func, arg1, arg2) {
}
};
If you want to run the thread later after the construction, you can first default-initialize std::thread, which will not start an actual thread, and then you can move a new std::thread instance with started thread into it later:
class ServerThread {
std::thread thr;
ServerThread() : thr() {
}
void StartThread(int arg1, double arg2) {
thr = std::thread(thread_func, arg1, arg2);
}
};
Related
I am trying to implement system-signal handling into my code, which looks basically like this
struct Foo{
bool should_stop_;
std::thread* _internal_thread_;
Foo(): should_stop_(false) {};
// this is what the thread does at heard
void operator()() {
while(!should_stop_) {
std::cout << "sleeping" <<endl;
sleep(1);
}
};
//start the execution in an thread; i.e. not blocking
void run() {
_internal_thread_ = new std::thread(std::ref(*this));
};
//end the thread execution, and join the thread
void stop() {
should_stop_ = true;
_internal_thread_->join();
}
};
int main () {
auto foo_ptr = new Foo();
foo_ptr->run(); // non blocking
try{
sleep(5); // while(True) {do_other_things();}
} catch(...) {
std::cout << "unexpected.\n";
}
foo_ptr->stop();
};
this works quite well for me [while the program could be in principle running indefinitely, I cut I short with five cycles, to demonstrate the call to stop()].
This does, however, not handle system-signals like SIGINT, SIGTERM etc. Having read the cpp-reference on signal() I wanted to wrap my Foo object into a functor and let it Handle the signal, aka interrupt the execution of foo by calling to stop as soon as the signal is received. I tried this:
struct myHandler {
Foo* foo_ptr_;
myHandler(Foo* foo_ptr) : foo_ptr_(foo_ptr) {};
void operator()(int signum) {
call(signum);
};
void call(int signum) {
std::cout << "Interrupt signal (" << signum << ") received.\n";
foo_ptr_->stop();
exit(signum);
};
};
int main() {
auto foo_ptr = new Foo();
auto my_sighandler = myHandler(foo_ptr);
signal(SIGINT, (void (*)(int))&my_sighandler); // -> should go through MyHandler::operator()
signal(SIGTERM, (void (*)(int))&my_sighandler::call); // -> should go through MyHandler::call
foo_ptr->run();
};
This, does not work for either of the two registered signals (SIGINT or SIGTERM). I can not find a viable solution to resolve this.
On my quick search I was able to find some solutions which go through the length of registering global volatile variables for which their classes [what is here Foo] listen to. However this would seriously break my class design as well as violate the program structure, which should be bottom-to-top.
Can anybody provide some hints here?
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 am trying to create a boost thread and I see the thread is created but the control does not come to the thread function. Can someone please explain why is it so?
Please see below for the code used.
header_file.h
class fa {
public:
fa();
~fa();
int init(void);
static void* clThreadMemFunc(void *arg) { return ((fa*)arg)->collectData((fa*)arg); }
void* collectData(fa *f );
private:
int m_data;
boost::thread *m_CollectDataThread;
};
`
test.cpp
int fa::init(void)
{
if (m_CollectDataThread== NULL)
{
printf("New Thread...\n");
try
{
m_CollectDataThread =
new boost::thread((boost::bind(&fanotify::clThreadMemFunc, this)));
}
catch (...){perror("Thread error ");}
printf("m_CollectDataThread: %p \n", m_CollectDataThread);
}
return 0;
}
void* fa::collectData(fa *f)
{
printf("In collectData\n");
int data = f->m_data;
printf("data %d",data);
}
The test.cpp is complied/built as a library (test.so) and another main function calls the init function. I see the variable m_collectDataThread value changing from null to some value (thread gets created) and also catch does not get any exception.
But I don't see any statement in collectData getting printed. Why is the thread not able to reach it?
Perhaps try adding a join.
E.g.
try
{
m_CollectDataThread =
new boost::thread(boost::bind(&fanotify::clThreadMemFunc, this));
m_CollectDataThread->join();
}
When you use boost::thread or std::thread you do not need old way of passing thread function (using static method and casting void * pointer), you can call class method directly:
class fa {
public:
fa();
~fa();
int init(void);
void collectData();
private:
int m_data;
boost::thread *m_CollectDataThread;
};
m_CollectDataThread = new boost::thread( &fa::collectData, this );
// or explicitly using bind
m_CollectDataThread = new boost::thread( boost::bind( &fa::collectData, this ) );
boost is C++ library, not C
I am trying to implement a simple thread starter class. Below you find a Simple base class implementation and 2 derived variations that are supposed to work as starters. The first one throws segfaults at static void* Threaded::run (void* self) sporadically. I suppose this might a pointer issue but I am not able to figure out why?
Does this in Threaded::start point to a wrong address or is there any other issue with my first derivation?
This is how it's used:
Thread thread (ptr_to_some_obj);
thread.start (&this_obj::callback);
thread.detach ();
Simple base class
class Threaded
{
public:
Threaded () {/* empty */}
virtual ~Threaded () {/* empty */}
/** Returns true if the thread was successfully started, false if there was an error starting the thread */
bool start ()
{
return (pthread_create (&_thread, NULL, run, this) == 0);
}
/** Implement this method in your subclass with the code which allows to gently stop execution. */
virtual void stop () = 0;
/** Will not return until the internal thread has exited. */
void wait ()
{
(void) pthread_join (_thread, NULL);
}
bool detach ()
{
return (pthread_detach (_thread) == 0);
}
protected:
/** Implement this method in your subclass with the code you want your thread to run. */
virtual void run () = 0;
static void* run (void* self)
{
((Threaded*) self) -> run ();
return NULL;
}
pthread_t _thread;
};
Derived class 1 (throws segfault at ((Threaded*) self) -> run (); above)
typedef void (*staticcall)(void*);
class Thread : public Threaded
{
public:
Thread (void* passthru)
:_call (NULL)
{
_passthru = passthru;
}
~Thread () { /* empty */ }
bool start (staticcall call)
{
_call = call;
assert (_call);
return start ();
}
void stop ()
{
// nothing
}
protected:
void run ()
{
(_call) (_passthru);
}
bool start ()
{
return Threaded::start ();
}
private:
Thread () { };
void* _passthru;
staticcall _call;
};
Derived class 2 (works, but i'd rather have Derived class 1 implementation)
typedef void (*staticcall)(void*);
class Thread2 : public Threaded
{
public:
Thread2 (void* passthru)
{
_passthru = passthru;
}
~Thread2 () { /* empty */ }
bool start (staticcall call)
{
_call = call;
assert (_call);
return start ();
}
void stop ()
{
// nothing
}
protected:
void run () { }
static void* run2 (void*)
{
(_call) (_passthru);
return NULL;
}
bool start ()
{
return (pthread_create (&_thread, NULL, run2, NULL) == 0);
}
private:
Thread2 () { };
static void* _passthru;
static staticcall _call;
};
void* Thread2::_passthru;
staticcall Thread2::_call;
As pointed out by molbdnilo:
pthread_create only queues the new thread. There are no guarantees regarding when the thread function will be called, and thread must be alive at that time.
Since I do not want to keep a list of spawned threads around I solved this with the use of pthread_cond_wait and pthread_cond_signal. The spawner will wait for a signal that is emitted by the method that runs in the thread. This way the thread creator won't destroy the thread object before the to-be-threaded method is called.
class ThreadSpawner
{
public:
ThreadSpawner ()
{
pthread_mutex_init (&MtxThreadStarter, 0);
pthread_cond_init (&CondThreadStarter, 0);
}
~ThreadSpawner ()
{
pthread_cond_destroy (&CondThreadStarter);
pthread_mutex_destroy (&MtxThreadStarter);
}
void spawn ()
{
Thread thread (pass_object);
pthread_mutex_lock (&MtxThreadStarter);
if (thread.start (&ThreadSpawner::callback))
{
// wait here for signal
pthread_cond_wait (&CondThreadStarter, &MtxThreadStarter);
thread.detach ();
}
pthread_mutex_unlock (&MtxThreadStarter);
}
static void callback (void* passthru)
{
// send signal to thread spawner
pthread_mutex_lock (&MtxThreadStarter);
pthread_cond_signal (&CondThreadStarter);
pthread_mutex_unlock (&MtxThreadStarter);
// do threaded work
}
private:
static pthread_mutex_t MtxThreadStarter;
static pthread_cond_t CondThreadStarter;
}
pthread_mutex_t ThreadSpawner::MtxThreadStarter = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t ThreadSpawner::CondThreadStarter = PTHREAD_COND_INITIALIZER;
Edit: a solution to let a thread execute as a method invokation
Well the solution I thought about in the recent discussion would work if the thread entry point was a simple function.
However, I suppose the idea is more to take advantage of an actual object, so that the thread body is actually an invokation of the body() method.
This is more tricky, since there must be a live instance of the derived class for the whole thread duration, and yet the original instance is likely to get out of scope after a start / detach sequence.
One possible (though somewhat costly) solution is to have the thread body stub create a local copy of the original instance on the stack. So the thread launcher will construct a thread object, and the thread itself will copy it.
With this system, you only need to make sure the original instance will be kept live in the interval between pthread_create and thread activation by the scheduler.
This requires a semaphore (which will be done by hand with a mutex/cond. var. pair for the 1.000.000th time, since bloody C++11 does not have one in store).
To hide this messy code inside the base class, you need to downcast the base pointer into the appropriate subclass type.
I resorted to templating the base class, though there might be smarter solutions out there. I just could not think of any.
To test the solution, I use a counter system that detects whether the original Thread instance has been deleted before the thread stub could make a local copy.
The SYNC compilation flag activates the semaphore. The expected program output is 0->0. If other numbers appear, it means some threads ran on messed-up instances.
I tested it on Ubuntu in a VM, and it seemed to work well enough.
#include <cstdlib>
#include <cstdio>
#include <cassert>
#include <thread> // sleep_for
#include <chrono> // milliseconds
#include <pthread.h>
#define SYNC // undefine this to see what happens without synchronization
typedef void *(*tEntryPoint) (void *);
#include <mutex>
#include <condition_variable>
class semaphore {
private:
std::mutex m;
std::condition_variable v;
int c;
public:
semaphore (int count = 0):c(count){}
void V()
{
#ifdef SYNC
std::unique_lock<std::mutex> l(m);
c++;
v.notify_one();
#endif
}
void P()
{
#ifdef SYNC
std::unique_lock<std::mutex> l(m);
while (c == 0) v.wait(l);
c--;
#endif
}
};
template<typename Derived>
class Threaded
{
public:
/** Returns true if the thread was successfully started, false if there was an error starting the thread */
bool start(void)
{
destructor_guard = new semaphore();
bool res = (pthread_create(&_thread, NULL, (tEntryPoint)entry_point, this) == 0);
if (res) destructor_guard->P(); // wait fot thread to start execution
delete destructor_guard;
return res;
}
/** This optional method will be executed after the thread main body */
virtual void stop() {}
/** Will not return until the internal thread has exited. */
void wait()
{
(void)pthread_join(_thread, NULL);
}
/** Will let the underlying task run independently */
bool detach()
{
return (pthread_detach(_thread) == 0);
}
private:
static void * entry_point(Derived * self)
{
Derived local_self = *self;
local_self.destructor_guard->V(); // original can be deleted
local_self.body();
local_self.stop();
return NULL;
}
pthread_t _thread;
semaphore* destructor_guard;
};
#define NUM_THREADS 9
#define REPEAT 3000
static int signature[NUM_THREADS + 1] = { 0, };
class Thread : public Threaded<Thread>
{
unsigned id;
public:
Thread(unsigned id) : id(id) {}
~Thread() { id = 0; }
void body(void)
{
signature[id%(NUM_THREADS+1)]++;
}
void stop(void)
{
std::this_thread::sleep_for(std::chrono::milliseconds(10));
signature[id%(NUM_THREADS+1)]++;
}
};
void launch_a_thread(int id)
{
Thread thread (id);
if (thread.start())
{
// thread.wait();
thread.detach();
}
}
int main(void)
{
for (unsigned i = 0; i != REPEAT*NUM_THREADS; i++) launch_a_thread(1+i%NUM_THREADS);
std::this_thread::sleep_for(std::chrono::milliseconds(100)); // leave enough time for free running threads to terminate
for (int i = 0 ; i <= NUM_THREADS ; i++) if (signature[i] != 2*REPEAT) printf ("%d -> %d\n", i, signature[i]);
return 0;
}
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 !