Boost logo

Boost :

Subject: Re: [boost] [thread] Do we can a non backward compatible version with non-blocking futures?
From: Lee Clagett (forum_at_[hidden])
Date: 2015-05-26 17:43:50


On Sun, May 24, 2015 at 7:35 AM, Vicente J. Botet Escriba <
vicente.botet_at_[hidden]> wrote:

> Le 23/05/15 19:05, Lee Clagett a écrit :
>
>> On Thu, May 21, 2015 at 5:13 PM, Vicente J. Botet Escriba <
>> vicente.botet_at_[hidden]> wrote:
>>
>> Le 21/05/15 17:11, Lee Clagett a écrit :
>>>
>>> A non-blocking future::then() is convenient for cases like the one
>>>> Vicente
>>>> described, but can the executor framework simulate the same behavior?
>>>>
>>>> Please , could you elaborate?
>>>
>>
>> boost::async and boost::future::then seem error prone due to ownership of
>> the execution handle.
>>
> Are talking here of blocking or non-blocking futures?
>

I was referring to non-blocking futures.

> If the destructor of the boost::future automatically
>> releases ownership, the execution handle cannot be managed.
>>
> Why?
>

It was incorrect of me to say that the execution handle cannot be managed
(see below). I thought the separate executor argument to boost::async could
make it more obvious that the executor object would control the lifetime of
the execution thread, and that it could prevent possible data races. I
doubt it will make data races to stack references easier to identify, but
it should help prevent threads after main, since the executor object could
force all execution threads to stop on its destruction instead. It wasn't
obvious previously, but I was wondering whether the detach on future
destruction should only be enabled when boost::async takes an executor
overload.

> It should
>> prevent threads after main, which never seem like a good idea.
>>
> Sorry, I don't understand, it should prevent what?
>

Static destruction could be complicated if there were multiple execution
threads after main. That was another issue brought up about not blocking on
destruction for the std async/future versions.

> Unfortunately, if client code throws before a boost::future::get() then
>> stack references can still be invalidated with the executor (see my prior
>> post) - but there are a number of ways to achieve this incorrect behavior
>> anyway.
>>
>> If boost::future::~future detaches the execution handle, its still
>> possible
>> to create an RAII wrapper that blocks if that behavior is desired. I don't
>> think the opposite is possible, so the change is more flexible.
>>
>>
>> Could you tell us more?
>
>
Inspired by ThreadRAII:

template<typename T>
class FutureRAII {
public:
  FutureRAII(boost::future<T>&& future)
    : future_(std::move(future)) {
  }

  ~FutureRAII() {
    try {
      if (future_.valid()) {
        future_.wait();
      }
    } catch (...) {
    }
  }

  boost::future<T>& future() { return future_; }

private:
  boost::future<T> future_;
};

The usual complications of calling a function after a move can appear if
future_ was the source of a move through the accessor.

Lee


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