Title
std::thread, std::call_once issue
Status
c++11
Section
[thread.thread.constr][thread.once.callonce]
Submitter
Peter Dimov

Created on 2008-09-15.00:00:00 last changed 153 months ago

Messages

Date: 2010-10-21.18:28:33

Proposed resolution:

Modify [thread.once.callonce] p1-p2 with the following:

template<class Callable, class ...Args>
  void call_once(once_flag& flag, Callable&& func, Args&&... args);

Given a function as follows:


template<typename T> typename decay<T>::type decay_copy(T&& v)
   { return std::forward<T>(v); }

1 Requires: The template parameters Callable and each Ti in Args shall be CopyConstructible if an lvalue and otherwise satisfy the MoveConstructible requirements. INVOKE(decay_copy(std::forward<Callable>(func), w1, w2, ..., wN decay_copy(std::forward<Args>(args))...) ([func.require]) shall be a valid expression for some values w1, w2, ..., wN, where N == sizeof...(Args).

2 Effects: Calls to call_once on the same once_flag object are serialized. If there has been a prior effective call to call_once on the same once_flag object, the call to call_once returns without invoking func. If there has been no prior effective call to call_once on the same once_flag object, the argument func (or a copy thereof) is called as if by invoking func(args) INVOKE(decay_copy(std::forward<Callable>(func)), decay_copy(std::forward<Args>(args))...) is executed. The call to call_once is effective if and only if func(args) INVOKE(decay_copy(std::forward<Callable>(func)), decay_copy(std::forward<Args>(args))...) returns without throwing an exception. If an exception is thrown it is propagated to the caller.

Date: 2010-02-12.00:00:00

[ 2010-02-12 Moved to Tentatively Ready after 5 postive votes on c++std-lib. ]

Date: 2010-02-11.00:00:00

[ 2010-02-11 Anthony updates wording. ]

Date: 2010-10-21.18:28:33

[ 2009-10 Santa Cruz: ]

See proposed wording for 929 for this, for the formulation on how to solve this. 929 modifies the thread constructor to have "pass by value" behavior with pass by reference efficiency through the use of the decay trait. This same formula would be useful for call_once.

Date: 2010-10-21.18:28:33

[ 2009-07 Frankfurt ]

Leave Open. Await decision for thread variadic constructor.

Date: 2010-10-21.18:28:33

[ Post Summit Anthony provided proposed wording. ]

Date: 2010-10-21.18:28:33

[ Summit: ]

Move to open.

Date: 2008-09-15.00:00:00

I notice that the vararg overloads of std::thread and std::call_once (N2723 [thread.thread.constr] and [thread.once.callonce]) are no longer specified in terms of std::bind; instead, some of the std::bind wording has been inlined into the specification.

There are two problems with this.

First, the specification (and implementation) in terms of std::bind allows, for example:

std::thread th( f, 1, std::bind( g ) );

which executes f( 1, g() ) in a thread. This can be useful. The "inlined" formulation changes it to execute f( 1, bind(g) ) in a thread.

Second, assuming that we don't want the above, the specification has copied the wording

INVOKE(func, w1, w2, ..., wN) (20.6.2) shall be a valid expression for some values w1, w2, ..., wN

but this is not needed since we know that our argument list is args; it should simply be

INVOKE(func, args...) (20.6.2) shall be a valid expression

History
Date User Action Args
2011-08-23 20:07:26adminsetstatus: wp -> c++11
2010-10-21 18:28:33adminsetmessages: + msg4242
2010-10-21 18:28:33adminsetmessages: + msg4241
2010-10-21 18:28:33adminsetmessages: + msg4240
2010-10-21 18:28:33adminsetmessages: + msg4239
2010-10-21 18:28:33adminsetmessages: + msg4238
2010-10-21 18:28:33adminsetmessages: + msg4237
2010-10-21 18:28:33adminsetmessages: + msg4236
2008-09-15 00:00:00admincreate