Blog Archive for / 2009 / 05 /
May 2009 C++ Standards Committee Mailing - Object Lifetimes and Threads
Monday, 18 May 2009
The May 2009 mailing for the C++ Standards Committee was published a couple of weeks ago. This is a minimal mailing between meetings, and only has a small number of papers.
The primary reason I'm mentioning it is because one of the papers
is concurrency related: N2880:
C++ object lifetime interactions with the threads API by
Hans-J. Boehm and Lawrence Crowl. Hans and Lawrence are concerned
about the implications of thread_local
objects with destructors, and
how you can safely clean up threads if you don't call join()
. The
issue arose during discussion of the proposed async()
function, but is generally applicable.
thread_local
variables and detached threads
Suppose you run a function on a thread for which you want the
return value. You might be tempted to use std::packaged_task<>
and std::unique_future<>
for this; after all it's almost exactly what they're designed for:
#include <thread> #include <future> #include <iostream> int find_the_answer_to_LtUaE(); std::unique_future<int> start_deep_thought() { std::packaged_task<int()> task(find_the_answer_to_LtUaE); std::unique_future<int> future=task.get_future(); std::thread t(std::move(task)); t.detach(); return future; } int main() { std::unique_future<int> the_answer=start_deep_thought(); do_stuff(); std::cout<<"The answer="<<the_answer.get()<<std::endl; }
The call to get()
will wait for the task to finish, but not the
thread. If there are no thread_local
variable
this is not a problem — the thread is detached so the library
will clean up the resources assigned to it automatically. If there
are thread_local
variables (used in
find_the_answer_to_LtUaE()
for example), then this
does cause a problem, because their destructors are not
guaranteed to complete when get()
returns. Consequently, the program may exit before the destructors of
the thread_local
variables have completed, and we have a
race condition.
This race condition is particularly problematic if the thread
accesses any objects of static storage duration, such as global
variables. The program is exiting, so these are being destroyed; if
the thread_local
destructors in the still-running thread
access global variables that have already been destroyed then your
program has undefined behaviour.
This isn't the only problem that Hans and Lawrence discuss —
they also discuss problems with thread_local
and threads
that are reused for multiple tasks — but I think it's the most
important issue.
Solutions?
None of the solutions proposed in the paper are ideal. I
particularly dislike the proposed removal of the detach()
member function from std::thread
. If
you can't detach a thread directly then it makes functions like
start_deep_thought()
much harder to write, and people
will find ways to simulate detached threads another way. Of the
options presented, my preferred choice is to allow registration of a
thread termination handler which is run after all
thread_local
objects have been destroyed. This handler
can then be used to set the value on a future or notify a condition
variable. However, it would make start_deep_thought()
more complicated, as std::packaged_task<>
wouldn't automatically make use of this mechanism unless it was
extended to do so — if it did this every time then it would make
it unusable in other contexts.
If anyone has any suggestions on how to handle the issue, please leave them in the comments below and I'll pass them on to the rest of the committee.
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.
"Introduction to Variadic Templates in C++0x" Article Online
Thursday, 07 May 2009
My latest article, Introduction to Variadic Templates in C++0x has been published at devx.com.
This article introduces the syntax for declaring and using variadic templates, along with some simple examples of variadic function templates and variadic class templates.
Posted by Anthony Williams
[/ news /] permanent link
Tags: article, variadic templates, C++0x
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-2025 Just Software Solutions Ltd. All rights reserved. | Privacy Policy