[threads / signals2] Win events replace by boost signals (threadsafe)
Hello,
I have to change win32 events with something portable so I decided to use
boost.signals2.
Right now I have something like:
ret = WaitForMultipleObjets{
switch(ret)
{
case Timeout: something; break;
case Event1: something; break;
case Event2: something; break;
}}
and I think that the good idea is to replace this with something like that:
for(;;){
Execute code from timeout, if event occurs interrupt and execute
code which is responsible for event handling}
but for test I write this:
boost::signals2::signal
On Monday, March 23, 2015 04:55 PM, Fu ji wrote:
Hello,
I have to change win32 events with something portable so I decided to use boost.signals2.
Right now I have something like:
ret = WaitForMultipleObjets{ switch(ret) { case Timeout: something; break; case Event1: something; break; case Event2: something; break; }}
and I think that the good idea is to replace this with something like that:
for(;;){ Execute code from timeout, if event occurs interrupt and execute code which is responsible for event handling}
but for test I write this:
boost::signals2::signal
signal; void SendSignal() { std::cout << "Send signal"; boost::this_thread::sleep_for(boost::chrono::milliseconds(200)); signal(); boost::this_thread::sleep_for(boost::chrono::milliseconds(2000)); }
int main() { boost::thread t1(SendSignal);
for (;;) { std::cout << "."; boost::this_thread::sleep_for(boost::chrono::milliseconds(100)); }
auto c = signal.connect([]() { std::cout << "Signal receive" << std::endl; boost::this_thread::sleep_for(boost::chrono::milliseconds(1000)); });
return 0;
At this point the thread detaches and the process exits: http://www.boost.org/doc/libs/1_57_0/doc/html/thread/thread_management.html#... You need to call t1.join() before exiting this scope. For exception safety, you'll probably want to use RAII so that the thread is joined on the destruction of a scoped object. Have a look at: http://www.boost.org/doc/libs/1_57_0/doc/html/thread/ScopedThreads.html#thre...
}
unfortunately this example is not working, what I've done wrong ?
Best regards
Ben
On 03/23/2015 11:59 AM, Ben Pope wrote:
On Monday, March 23, 2015 04:55 PM, Fu ji wrote:
int main() { boost::thread t1(SendSignal);
for (;;) { std::cout << "."; boost::this_thread::sleep_for(boost::chrono::milliseconds(100)); }
auto c = signal.connect([]() //...
At this point the thread detaches and the process exits: http://www.boost.org/doc/libs/1_57_0/doc/html/thread/thread_management.html#...
You need to call t1.join() before exiting this scope.
That's true but the end of main() will never be reached (and also the signal will never be connected) since the for(;;)-loop will print dots and sleep forever before actually doing any work. Norbert
On Monday, March 23, 2015 07:08 PM, Norbert Wenzel wrote:
On 03/23/2015 11:59 AM, Ben Pope wrote:
On Monday, March 23, 2015 04:55 PM, Fu ji wrote:
int main() { boost::thread t1(SendSignal);
for (;;) { std::cout << "."; boost::this_thread::sleep_for(boost::chrono::milliseconds(100)); }
auto c = signal.connect([]() //...
At this point the thread detaches and the process exits: http://www.boost.org/doc/libs/1_57_0/doc/html/thread/thread_management.html#...
You need to call t1.join() before exiting this scope.
That's true but the end of main() will never be reached (and also the signal will never be connected) since the for(;;)-loop will print dots and sleep forever before actually doing any work.
D'oh! I saw the less obvious problem first and went with it. Does anybody program with explicit threads any more? :P Ben
I know about join and detach anyway thank you for advice.
Working version:
for(;;){
auto c = signal.connect([]()
{
ThreadHandle->interrupt();
//code for handling event1
});
try
{
//code for timeout
}
catch (boost::thread_interrupted&)
{
//thread interrupted by signal listener
boost::this_thread::sleep_for(boost::chrono::milliseconds(1000));
}}
when signal is 'catched' I interrupt main flow (timeout) and do stuff which
should be done if event occurs.
2015-03-23 12:24 GMT+01:00 Ben Pope
On Monday, March 23, 2015 07:08 PM, Norbert Wenzel wrote:
On 03/23/2015 11:59 AM, Ben Pope wrote:
On Monday, March 23, 2015 04:55 PM, Fu ji wrote:
int main() { boost::thread t1(SendSignal);
for (;;) { std::cout << "."; boost::this_thread::sleep_for(boost::chrono::milliseconds( 100)); }
auto c = signal.connect([]() //...
At this point the thread detaches and the process exits: http://www.boost.org/doc/libs/1_57_0/doc/html/thread/thread_ management.html#thread.thread_management.thread.destructor
You need to call t1.join() before exiting this scope.
That's true but the end of main() will never be reached (and also the signal will never be connected) since the for(;;)-loop will print dots and sleep forever before actually doing any work.
D'oh! I saw the less obvious problem first and went with it.
Does anybody program with explicit threads any more? :P
Ben
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/ mailman/listinfo.cgi/boost
AMDG On 03/23/2015 02:55 AM, Fu ji wrote:
I have to change win32 events with something portable so I decided to use boost.signals2.
Boost.Signals2 isn't really a good tool for synchronization. That isn't its purpose. Try using boost::condition_variable from Boost.Thread, instead. In Christ, Steven Watanabe
Condition variable can be a really good solution to my problem, I have only
problem with WaitForMultipleObjects because with cond_var I have to check
all "events" in loop with cond.timed_wait. There is a better solution ?
Best Regards,
2015-03-23 16:41 GMT+01:00 Steven Watanabe
AMDG
On 03/23/2015 02:55 AM, Fu ji wrote:
I have to change win32 events with something portable so I decided to use boost.signals2.
Boost.Signals2 isn't really a good tool for synchronization. That isn't its purpose. Try using boost::condition_variable from Boost.Thread, instead.
In Christ, Steven Watanabe
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/ mailman/listinfo.cgi/boost
On 24/03/2015 22:28, Fu ji wrote:
Condition variable can be a really good solution to my problem, I have only problem with WaitForMultipleObjects because with cond_var I have to check all "events" in loop with cond.timed_wait. There is a better solution ?
If the events are intended to signal that data is available somewhere, then you could consider replacing them with futures instead, which can supply the data at the same time. There is a way to wait for one or all of a set of multiple futures, although not with a timeout.
I read about condition variable and it's also not the best idea, because we
can receive signal only if we actually wait in this time. For example:
void setcondvar()
{
boost::this_thread::sleep_for(boost::chrono::milliseconds(200));
std::cout << "Set" << std::endl;
cond.notify_all();
std::cout << "After" << std::endl;
}
int main()
{
boost::mutex CondMutex;
boost::thread t1(setcondvar);
t1.join();
std::cout << "Before wait" << std::endl;
boost::unique_lockboost::mutex lock(CondMutex);
bool result = cond.timed_wait(lock,
boost::posix_time::milliseconds(1000));
std::cout << result;
return 0;
}
and we have 0 as result. Probably i should write some wrapper on cond
variable if i would like to have this functionality.
2015-03-24 23:40 GMT+01:00 Gavin Lambert
On 24/03/2015 22:28, Fu ji wrote:
Condition variable can be a really good solution to my problem, I have only problem with WaitForMultipleObjects because with cond_var I have to check all "events" in loop with cond.timed_wait. There is a better solution ?
If the events are intended to signal that data is available somewhere, then you could consider replacing them with futures instead, which can supply the data at the same time. There is a way to wait for one or all of a set of multiple futures, although not with a timeout.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/ mailman/listinfo.cgi/boost
On 25/03/2015 20:57, Fu ji wrote:
I read about condition variable and it's also not the best idea, because we can receive signal only if we actually wait in this time. For example:
That's the purpose of the mutex. You have to lock the mutex, *then* check for the condition which would wake you up, and only then after this fails should you wait on the cond_var. You also have to test the condition after you wake up, as you might be woken spuriously. The mutex also has to protect anything that can change the true/false state of the conditional test you're doing, before you notify. This way, the notify thread can't miss waking up any thread that hasn't gone to sleep yet because it won't have tested the condition yet.
boost::unique_lockboost::mutex lock(CondMutex); bool result = cond.timed_wait(lock, boost::posix_time::milliseconds(1000));
This sort of thing is really unsafe, for the above reasons.
and we have 0 as result. Probably i should write some wrapper on cond variable if i would like to have this functionality.
Yes, you will need to write a wrapper that has some state to protect with the lock and that you can check when woken (eg. a bool is_event_set). You'll also have to decide whether you're trying to emulate auto-reset or manual-reset events, since they have different behaviour in the woken thread.
On 25/03/2015 07:57, Fu ji wrote:
I read about condition variable and it's also not the best idea, because we can receive signal only if we actually wait in this time. For example:
void setcondvar() { boost::this_thread::sleep_for(boost::chrono::milliseconds(200)); std::cout << "Set" << std::endl; cond.notify_all(); std::cout << "After" << std::endl; }
int main() { boost::mutex CondMutex;
boost::thread t1(setcondvar); t1.join();
std::cout << "Before wait" << std::endl;
boost::unique_lockboost::mutex lock(CondMutex); bool result = cond.timed_wait(lock, boost::posix_time::milliseconds(1000));
std::cout << result;
return 0; }
Code that looks like that is wrong. Always have a flag protected by the mutex, always respond to the cond wait returning by checking the flag and waiting again unless timeout.
participants (6)
-
Ben Pope
-
Fu ji
-
Gavin Lambert
-
james
-
Norbert Wenzel
-
Steven Watanabe