Boost logo

Boost :

Subject: Re: [boost] [thread] Questions about broken_promise
From: Jonathan Wakely (jwakely.boost_at_[hidden])
Date: 2013-07-29 04:57:26


On 28 July 2013 22:24, Klaim - Joël Lamotte wrote:
> I have a few questions concerning broken promises (exception):
>
> 1. is the broken_promise exception a standard, or future standard behaviour?
> So far I assumed it wasn't because
> http://en.cppreference.com/w/cpp/thread/promise/~promise
> don't say anything about this and I only read about broken_promise
> exceptions on Boost.Thread
> documentation.

Did you try searching the standard?

If a std::promise with an associated shared state is destroyed before
making the state ready it sets an exception of type std::future_error
with an error condition of std::future_errc::broken_promise.

> I would like to know if I should expect the future standard library to have
> the same concept.
> I see no configuration macro to deactivate these exceptions. I don't want
> to actually, but
> if I'm correct that it's not standard or future standard, then it's
> surprising that I can't setup
> a standard-like setup.

You're not correct.

> 2. I have a case that could be summarized like this:
>
> /////////////////////////////////////////////
>
> Updated by thread A:
>
> struct X { /*... */ };
>
> struct K
> {
> future<shared_ptr<X,U>> m_ft_x;
> shared_ptr<X,U> m_x;
>
> K( Foo& foo )
> : m_ft_x( foo.create<X>() )
> {}
>
> void update() // this is always called by a loop in the thread A
> {
> if( !m_x )
> {
> if( m_ft_x.has_value() )

future::has_value() is non-standard. You can use a timed-waiting
function instead.

> m_x = m_ft_x.get();
> }
> else
> work();
> }
>
> void work(); // uses m_x
>
> };
>
>
> Updated by thread B:
>
> // special deleter which will just push a task in Foo work queue for
> deleting the object
> // in sync with thread B
> struct U { /* ... */ };
>
> struct Foo
> {
> template< class T >
> future<shared_ptr<T,U>> create() // will push a creation task in a
> work queue updated in update()
>
> void update(); // called by a loop in the thread B, will execute all
> the work pushed in the work queue.
>
> };
>
> /////////////////////////////////////////////
>
> (this is an exageratedly simplified version of what I'm doing)
> It works nicely (even if I think it could be improved with future.then and
> other tools)
> but there is a minor problem appearing when an instance of
> K is constructed then almost immediately destructed,
> before the instance of Foo executed the creation of the X instance.
> In this case, visual studio (which is configured to detect all throw calls)
> detect a broken_promise exception thrown from the
> destructor of the promise which was in the code generated by Foo::create()
> and pushed in a work queue.
>
> I look at the destructor and I see:
>
> if(!future_->done && !future_->is_constructed)
> {
>
> future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()),
> lock);
> }
>
> Here is the full copy_exception code:
>
> template <class T>
> inline
> exception_ptr
> copy_exception( T const & e )
> {
> try
> {
> throw enable_current_exception(e);
> }
> catch(
> ... )
> {
> return current_exception();
> }
> }
>
> This code triggers actually two "first-chance" exceptions this is the first
> one)
> which are catch immediately intentionally.
>
> My question is: why is copy_exception necessary and why does it have to do
> it this way?

N.B. std::copy_exception was renamed make_exception_ptr before the
final C++11 standard, I guess Boost didn't follow that change.

How else do you create an exception_ptr that refers to an active
exception object (i.e. one that has been thrown, so is created on
whatever special stack the compiler uses for exceptions)?

> It's a very minor problem as just re-setting my visual studio debugging
> settings to default
> makes the exception transparent -only visible in the console log.
> However each time I activate debug breaking on all c++ exception so that I
> can debug
> some potential issues, I can have a breakpoint which is actually "noise" as
> it is only used
> to implement a copy of exception.
> Is it possible to eliminate this noise? Or, as I'm guessing, is there a
> language or compiler limitation
> which forces this code to be written this way?

The library is following the standard, if your IDE flags that as an
issue it's a problem with your IDE.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk