Boost logo

Threads-Devel :

Subject: Re: [Threads-devel] threads-devel Digest, Vol 69, Issue 3
From: Patrick Grace (patrick.grace_at_[hidden])
Date: 2014-02-19 12:35:09


threads-devel_at_[hidden]

> -----Original Message-----
> From: threads-devel [mailto:threads-devel-bounces_at_[hidden]] On
Behalf
> Of threads-devel-request_at_[hidden]
> Sent: 12 February 2014 17:00
> To: threads-devel_at_[hidden]
> Subject: threads-devel Digest, Vol 69, Issue 3
>
> Send threads-devel mailing list submissions to
> threads-devel_at_[hidden]
>
> To subscribe or unsubscribe via the World Wide Web, visit
> http://lists.boost.org/mailman/listinfo.cgi/threads-devel
> or, via email, send a message with subject or body 'help' to
> threads-devel-request_at_[hidden]
>
> You can reach the person managing the list at
> threads-devel-owner_at_[hidden]
>
> When replying, please edit your Subject line so it is more specific than
"Re:
> Contents of threads-devel digest..."
>
>
> Today's Topics:
>
> 1. Re: boost::barrier - mechanism to deal exceptions
> (Vicente J. Botet Escriba)
>
>
> ----------------------------------------------------------------------
>
> Message: 1
> Date: Tue, 11 Feb 2014 19:33:58 +0100
> From: "Vicente J. Botet Escriba" <vicente.botet_at_[hidden]>
> To: "Discussions about the boost.thread library"
> <threads-devel_at_[hidden]>
> Subject: Re: [Threads-devel] boost::barrier - mechanism to deal
> exceptions
> Message-ID: <52FA6D16.2080209_at_[hidden]>
> Content-Type: text/plain; charset="iso-8859-1"; Format="flowed"
>
> Le 11/02/14 14:12, Patrick Grace a ?crit :
> >
> > Hi
> >
> > I had built my own thread aligner before I found out about
> > boost::barrier when watching Rob Stewart's talk at BoostCon 2013.
> > Then I compared my thread aligner with boost::barrier and found they
> > did the same thing. boost::barrier had the advantage of being reusable
> > but mine had a mechanism to deal with exceptions (to prevent threads
> > waiting on a thread that will never arrive because it has thrown an
> > exception). I combined the 2 versions together and this is what I
> > came up with:
> >
> > class cascade_exception {}; // used to release threads waiting in
> > thread_barrier::wait() if an exception occurs in another thread
> >
> > class thread_barrier {
> >
> > // use to align threads similar to boost::barrier, it may be
> > reused
> >
> > unsigned counter_;
> >
> > unsigned counter_init_;
> >
> > unsigned generation_{};
> >
> > bool exception_flag_{false};
> >
> > std::mutex mutex_;
> >
> > std::condition_variable cv_;
> >
> > public:
> >
> > thread_barrier(const thread_barrier&) = delete;
> >
> > thread_barrier& operator=(const thread_barrier&) = delete;
> >
> > explicit thread_barrier(unsigned n=0) : counter_(n),
> > counter_init_(n) {}
> >
> > void set_nthreads(unsigned n) {
> >
> > counter_ = counter_init_ = n;
> >
> > exception_flag_ = false;
> >
> > generation_ = 0;
> >
> > }
> >
> > void wait() {
> >
> > std::unique_lock < std::mutex > lock(mutex_);
> >
> > unsigned gen = generation_;
> >
> > if (--counter_ == 0) {
> >
> > ++generation_;
> >
> > counter_ = counter_init_;
> >
> > cv_.notify_all();
> >
> > return;
> >
> > }
> >
> > while (gen == generation_) {
> >
> > if ( exception_flag_ ) throw cascade_exception{};
> >
> > cv_.wait(lock);
> >
> > }
> >
> > }
> >
> > void setExceptionFlag() {
> >
> > std::unique_lock < std::mutex > lock(mutex_);
> >
> > exception_flag_ = true;
> >
> > cv_.notify_all();
> >
> > }
> >
> > };
> >
> > I have highlighted all the parts that deal with exception handling.
> > This is how I use it:
> >
> > void task(thread_barrier& barrier) {
> >
> > try {
> >
> > // ....
> >
> > barrier.wait();
> >
> > // ....
> >
> > } catch ( cascade_exception& ) {
> >
> > // do nothing
> >
> > } catch (...) {
> >
> > barrier.setExceptionFlag();
> >
> > throw; // transfers the exception to the promise/future
> >
> > }
> >
> > }
> >
> > If one thread throws an exception (other than cascade_exception) it
> > should be caught before the thread is ended and setExceptionFlag() is
> > called which causes all the other threads to throw a
> > cascade_exception. All threads can now end gracefully and the
> > original exception gets thrown when future::get() is called (I use
> > std::packaged_task(task) ... ).
> >
> > Please feel free to add this exception handling mechanism to
> > boost::barrier. I think it needs some sort of exception handling.
> >
> >
> Hi,
>
> Interesting use case.
>
> I have a question. What would you do when the task received a cascade
> exception? The task is not completely finished as an exception has been
throw
> on the call to wait.
>
> Vicente
> -------------- next part --------------
> HTML attachment scrubbed and removed
>
> ------------------------------
>
> Subject: Digest Footer
>
> _______________________________________________
> threads-devel mailing list
> threads-devel_at_[hidden]
> http://lists.boost.org/mailman/listinfo.cgi/threads-devel
>
>
> ------------------------------
>
> End of threads-devel Digest, Vol 69, Issue 3
> ********************************************
Vicente

In my case I am happy to let all threads exit their respective task if one
exception is thrown. The purpose of the cascade exception is just to free
up any waiting threads and get them to jump over the now-meaningless
data-merging operation that I do after the barrier. Once the cascade
exception is caught I allow the task to exit without doing anything else as
the originating exception will be dealt with outside the task. (In my case
I have all threads running the same task with different data.) Does that
answer your question?

Patrick


Threads-Devel list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk