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
> m_ft_x; shared_ptr 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
> 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.