[thread] Questions about broken_promise
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.
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.
2. I have a case that could be summarized like this:
/////////////////////////////////////////////
Updated by thread A:
struct X { /*... */ };
struct K
{
future
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.
On Mon, Jul 29, 2013 at 10:57 AM, Jonathan Wakely
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 didn't yet, thanks for pointing that.
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.
Ok.
future::has_value() is non-standard. You can use a timed-waiting function instead.
Yes, my real code doesn't do exactly that and is more like using .then(). I can't use time waiting functions in my case.
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)?
I see.
The library is following the standard, if your IDE flags that as an issue it's a problem with your IDE.
I believe then that's it's more a collaboration issue: the IDE doesn't "flag" the exception thrown, what it does is just log it by default in the debug console. However, if you set the IDE to break each time any C++ exception is thrown, then it will break in the throw in copy_exception() and current_exception(). So the IDE behave correctly, but have no way to know that these throw are an implementation detail. Just ignoring the breakpoint or setting the IDE to default (break only on some specific throw and just log throws that are catch) does work fine so I'll work this way instead for now. It's only in some kind of debugging session that the throw in these functions can be noisy. Joel Lamotte
participants (2)
-
Jonathan Wakely
-
Klaim - Joël Lamotte