Boost logo

Boost :

Subject: [boost] [thread] Questions about broken_promise
From: Klaim - Joël Lamotte (mjklaim_at_[hidden])
Date: 2013-07-28 17:24:23


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<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() )
                 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?
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?

Thanks for your time.

Joel Lamotte


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