Re: [Boost-bugs] [Boost C++ Libraries] #10056: boost::promise runs arbitrary code while holding mutex lock

Subject: Re: [Boost-bugs] [Boost C++ Libraries] #10056: boost::promise runs arbitrary code while holding mutex lock
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2014-05-31 00:38:06


#10056: boost::promise runs arbitrary code while holding mutex lock
------------------------------------------------+----------------------
  Reporter: Jonathan Wakely <jwakely.boost@…> | Owner: viboes
      Type: Bugs | Status: assigned
 Milestone: To Be Determined | Component: thread
   Version: Boost 1.54.0 | Severity: Problem
Resolution: | Keywords:
------------------------------------------------+----------------------

Comment (by jwakely.boost@…):

 call_once adds a bit of overhead, but is only a bottleneck if multiple
 threads are trying to make the shared state ready at the same time, and
 since all but the first are going to fail with an exception containing
 promise_already_satisfied it doesn't really matter if they're blocked on
 call_once.

 From memory, my design is roughly:

 {{{
 void
 state::set(function<unique_ptr<Result>()> setter)
 {
   unique_lock<mutex> l(m_mutex, defer_lock);
   call_once(m_once, &state::do_set, this, ref(setter), ref(l));
   if (!l.owns_lock())
     throw_promise_already_satisfied_err();
 }

 void
 state::do_set(function<unique_ptr<Result>()>& setter, unique_lock<mutex>&
 l)
 {
   auto result = setter(); // run without lock held
   l.lock();
   m_result.swap(result); // non-blocking
 }
 }}}

 `Result` is a wrapper for the result, containing `exception_ptr` and `R`
 for a `future<R>`, or `exception_ptr` and `R*` for `future<R&>`, or just
 `exception_ptr` for `future<void>`. The `setter` function creates a new
 `Result` and sets its members (possibly by running a deferred function or
 a packaged_task's callable) and any copy construction of `R` happens
 inside that setter, before the mutex is locked.

 The mutex is locked to transfer the `Result` into `m_result`, and also
 locked by waiting functions checking whether `m_result != nullptr`.

 I'm not sure that Boost's implementation should support my strange
 scenario - I'm still not certain my testcase is valid. No other
 implementations seem to support it, and maybe noone really cares if it
 works, so a severe refactoring probably isn't worth it.

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/10056#comment:6>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:16 UTC