June 2009 C++ Standards Committee Mailing - New Working Draft and Concurrency Papers
Wednesday, 24 June 2009
The June 2009 mailing for the C++ Standards Committee was published today. This is the pre-meeting mailing for the upcoming committee meeting. Not only does it include the current C++0x working draft, but there are 39 other papers, of which 6 are concurrency related.
Concurrency-related papers
- N2880: C++ object lifetime interactions with the threads API
This is a repeat of the same paper from the May 2009 mailing. It is referenced by several of the other concurrency papers.
- N2888: Moving Futures - Proposed Wording for UK comments 335, 336, 337 and 338
This is the first of my papers in this mailing. The current working draft restricts
std::unique_future
to beMoveConstructible
, but notMoveAssignable
. It also restrictsstd::shared_future
in a similar way, by making itCopyConstructible
, but notCopyAssignable
. This severely limits the potential use of such futures, so the UK panel filed comments on CD1 such as UK comment 335 which requested relaxation of these unnecessary restrictions. This paper to provide a detailed rationale for these changes, along with proposed wording.- N2889: An Asynchronous Call for C++
This is the first of two papers in the mailing that proposes a
std::async()
function for starting a task possibly asynchronously and returning a future for the result from that task. This addresses a need identified by UK comment 329 on CD1 for a simple way of starting a task with a return value asynchronously.- N2901: A simple async()
This is the second of the papers in the mailing that proposes a
std::async()
function for starting a task possibly asynchronously and returning a future for the result from that task.The primary difference between the papers is the type of the returned future. N2889 proposes a new type of future (
joining_future
), whereas N2901 proposes usingstd::unique_future
. There are also a few semantic differences surrounding whether tasks that run asynchronously aways do so on a new thread, or whether they may run on a thread that is reused for multiple tasks. Both papers provide a means for the caller to specify synchronous execution of tasks, or to allow the implementation to decide between synchronous execution and asynchronous execution on a case-by-case basis. N2901 also explicitly relies on the use of lambda functions orstd::bind
to bind parameters to a call, whereas N2889 supports specifying function arguments as additional parameters, as per thestd::thread
constructor (see my introduction to starting threads with arguments in C++0x).Personally, I prefer the use of
std::unique_future
proposed in N2901, but I rather like the argument-passing semantics of N2889. I also think that thethread_local
issues can be addressed by my proposal for that (N2907, see below). A final concern that I have is that calling the task insidefuture::get()
can yield surprising behaviour, as futures can be passed across threads, so this may end up being called on another thread altogether. For synchronous execution, I would prefer invoking the task inside thestd::async
call itself, but delaying it to theget()
does allow for work-stealing thread pools.- N2907: Managing the lifetime of thread_local variables with contexts
This is the second of my papers in this mailing. It proposes a potential solution to the lifetime-of-
thread_local
-variables issues from N2880 discussed in last month's blog post.The idea is that you manage the lifetime of
thread_local
variables by constructing an instance of a new classstd::thread_local_context
. When thestd::thread_local_context
instance is destroyed, allthread_local
variables created in that context are also destroyed. You can then construct a subsequent instance ofstd::thread_local_context
, and create newthread_local
instances in that new context. This means that you can reuse a thread for multiple unrelated tasks, without "spilling"thread_local
variables from an earlier task into later tasks. It can also be used with astd::async()
function to ensure that thethread_local
variables are destroyed before the associated future is made ready.- N2917: N2880 Distilled, and a New Issue With Function Statics
This is Herb Sutter's take on the issues from N2880. He starts with a general discussion of the issue with detached threads and static destruction of globals, and then continues with a discussion of the issues surrounding the destruction of function-scoped
thread_local
variables. In particular, Herb focuses on something he calls Functionthread_local
statics poisoningthread_local
destructors — if the destructor of athread_local
objectx
calls a function that itself uses a function-scopethread_local
y
, then the destructor ofy
might already have been called, resulting in undefined behaviour.I found Herb's coverage of the issues surrounding detached threads dismissive of the idea that people could correctly write manual synchronization (e.g. using a
std::condition_variable
or astd::unique_future
), even though this is common practice amongst those using POSIX threads (for example, in David Butenhof's Programming with POSIX Threads, he says "pthread_join is a convenience, not a rule", and describes examples using detached threads and condition variables to signal when the thread is done). I can see many possibilities for such usage, so as a consequence, I am personally in favour of his "solution" 1D: leave things as they are with regard to detached threads — it is already undefined behaviour to access something after its destruction.However, the issue Herb raises with regard to order of destruction for
thread_local
variables is important, and not something that mystd::thread_local_context
proposal addresses. As Herb points out, the problem does exist with regard to function-localstatic
variables already —thread_local
just amplifies the problem. I am inclined to go with what POSIX threads does, and whatboost::thread_specific_ptr
does: make them "phoenix" variables that are re-initialized when accessed after destruction, and are thus added back onto the destructor list. This is Herb's solution 2B.
Other papers
Now that CD1 is out, and the committee is trying to get things pinned down for CD2, Concepts are getting a lot of discussion. There are therefore several papers on Concepts in the mailing. There are also papers on automatically defining move constructors, revised wording for lambdas, a proposal for unifying the function syntax, and several others. Check out the full list of papers for details.
Your comments
Do you have any comments on the papers (especially the concurrency
ones, but if you have any comments on the others I'd like to know
too)? Which std::async
proposal do you prefer, or do you
like aspects of both or neither? Do you think that
thread_local_context
objects combined with resurrecting
thread_local
objects on post-destruction access solves
the thread_local
issues?
Let me know by posting a comment.
Posted by Anthony Williams
[/ cplusplus /] permanent link
Tags: C++0x, C++, standards, concurrency
Stumble It! | Submit to Reddit | Submit to DZone
If you liked this post, why not subscribe to the RSS feed or Follow me on Twitter? You can also subscribe to this blog by email using the form on the left.
Design and Content Copyright © 2005-2024 Just Software Solutions Ltd. All rights reserved. | Privacy Policy
No Comments