Blog Archive
just::thread C++0x Thread Library V1.7.0 Released
Wednesday, 05 October 2011
I am pleased to announce that version 1.7.0
of just::thread
,
our C++0x Thread Library
has just been released.
This release adds official support for gcc v4.4 on Centos 6, so Just::Thread is now supported on Centos, Fedora, Ubuntu and Debian Linux distributions, as well as Microsoft Windows and Apple MacOSX.
The main change with this release is an enhancement to
the std::async
implementation. With this enhanced scheduler, the default launch
policy (std::launch::async | std::launch::deferred
)
will defer forcing a decision until either enough resources become
available to schedule the task as std::launch::async
,
or the task is forced to be scheduled
as std::launch:deferred
by a call to a waiting function
(get()
, wait()
, wait_for()
or
wait_until()
). This will allow more tasks to be
scheduled as std::launch::async
overall, and allow your
application to make better use of the available hardware
concurrency.
The implementation of recursive mutexes has been overhauled, leading to much faster lock and unlock times than in previous releases.
This release also provides debugger visualizers for Microsoft Visual Studio, to better show the state of Just::Thread objects such as futures. This will provide greater insight into the state of your program, and allow easier debugging.
Purchase your copy and get started with the C++0x thread library now.
As usual, existing customers are entitled to a free upgrade to V1.7.0 from all earlier versions.
Posted by Anthony Williams
[/ news /] permanent link
Tags: multithreading, concurrency, 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.
Thread-Safe Copy and Move Constructors
Wednesday, 17 August 2011
This is a guest post by Michael Spertus. Michael is a Distinguished Engineer at Symantec. He is also a C++ Standards Committee member and teaches the graduate C++ sequence at the University of Chicago. He can be contacted at mike_spertus@symantec.com.
This guest column discusses writing thread-safe constructors. As we will see, this is more difficult than it seems. Fortunately, we will also see that C++11 offers a very pretty solution to this problem that nicely illustrates the synergy of the new features introduced in C++11.
The problem
If you have a class that supports locking of objects to serialize access to a given object, you probably want the class' copy constructor and move constructor (if it has one) to lock the source object to get a consistent snapshot of the source object so the destination object isn't messed up if the source changes in the middle of the copy or move.
This isn't nearly as easy as it sounds. In the following class, a
mutex is used to try to enforce the invariant that i_squared
should always be the square of i
.
class A { public: A(_i = 0) { set(_i); } set(int _i) { std::lock_guard<std::mutex> lock(mtx); i = _i; i_squared = i*i; } ... private: std::mutex mtx; int i; int i_squared; };
Unfortunately, the default copy constructor doesn't acquire the
mutex, so in code like the following, f
can copy a "half set" version of a
if another thread modifies a
at the same time.
void f(A &a) { A a2 = a; ... }
First attempt
A naive attempt is to acquire the lock in the constructor body just like in a thread-safe method.
class A { public: A(const A &a) : i(a.i), i_squared(a.i_squared) { std::lock_guard<std::mutex> lock(a.mtx); // Too late! } ... };
Unfortunately, this fares no better
as i
and i_squared
are
copied before we acquire the lock.
Second attempt
One approach would be to simply not lock in the copy constructor at all and just manually lock objects you want to copy:
void f(A &a) { std::lock_guard<std::mutex> lock(a.mtx); A a2 = a; ... }
This approach deserves careful consideration. For classes which
are not usually shared between threads or which need locking granularity
at a different level than their internal operations, managing locks
within the class can be an antipattern. This concern was a primary reason
why C++11 does not have an equivalent to the SynchronizedCollection
wrapper found in Java and C#. For example, synchronized
collections make it easy to inadvertently loop through a collection believing
your code is thread-safe even though the collection could change between
individual operations on the collection during the loop. Of course, if
we decide not to have A
's copy constructor lock, then A::set()
should not lock either.
Still, it remains a very common and useful pattern for classes designed for shared
use to have all their internal operations acquire the
lock (i.e.,
monitors/synchronized classes).
If A
is a synchronized class that locks its methods internally, it would
be very confusing and prone to intermittent errors to still have to manually acquire
the
lock whenever an object is copied or moved. Also, generic
code, which doesn't know about A::mtx
is unlikely to work
properly.
Third attempt
One thing we can do is dispense with member initialization lists in constructors altogether
class A { public: A(const A &a) { std::lock_guard<std::mutex> lock(a.mtx); i = a.i; i_squared = a.i_squared; } ... };
This solution is awkward at best if any bases or members don't have default constructors, have reference type, or are const. It also seems unfair to have to pay an efficiency penalty (for constructing and assigning separately) just because there is no place to put the lock. In practice, I also suspect intermittent errors will creep into large code bases as programmers carelessly add a base or member initializer to the constructor. Finally, it just isn't very satisfying to have to just discard core parts of constructor syntax just because your class is synchronized.
Fourth attempt
Anthony Williams has suggested implementing serialized classes using a wrapper class like:
struct PrivateBaseForA { int i; int i_squared; }; class A: private PrivateBaseForA { mutable std::mutex mtx; public: A(int _i = 0) { set(_i); } void set(int _i) { std::lock_guard<std::mutex> lock(mtx); i = _i; i_squared = _i*_i; } A(const A& other): PrivateBaseForA((std::lock_guard<std::mutex>(other.mtx),other)) {} };
Anthony makes slick use of double-parens to use the comma operator. If you
wanted to avoid this, you could have PrivateBaseForA
's constructor take a lock.
Again, this is not yet a very satisfying solution because writing a wrapper class for every synchronized class just to get a properly locked copy constructor is clumsy and intrusive.
Finally, the C++11 approach
Fortunately, C++11 offers a nice solution that really illustrates how beautifully and powerfully the features of C++11 work together. C++11 supports forwarding one constructor to another, which gives us an opportunity to grab the mutex before any copying or moving takes place:
class A { private: A(const A &a, const std::lock_guard<std::mutex> &) : i(a.i), i_squared(a.i_squared) {} public: A(const A &a) : A(a, std::lock_guard<std::mutex>(a.mtx)) {} ... };
This solution locks the entire constructor, protects against races resulting from forgetting the manual lock, works with generic code, and doesn't require the creation of artificial wrapper classes.
While I think this is clearly the preferred solution, it is not perfect. To begin with, it is more obscure and guru-like than I would wish for such a common situation. Secondly, constructor forwarding is not yet implemented by any major C++ compiler (although the recently approved standard should change that soon). Finally, we lose the benefit of compiler generated copy constructors. If we added an i_cubed field to A that also needed to be kept consistent with i, we might forget to update the private constructor. Perhaps this will be a further opportunity for the next C++ standard (C++1y?). In the meantime, C++11 provides a powerful new solution to the everyday problem of writing thread-safe copy and move constructors.
One final note is to mention that although this article focused on copy constructors, everything applies equally to move constructors. Indeed, any constructor that needs to acquire any lock whatsoever (e.g., a database lock) for its entire duration can apply these techniques.
Posted by Anthony Williams
[/ threading /] permanent link
Tags: multithreading, copying
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.
Simplify Code by Encapsulating Locks
Wednesday, 15 June 2011
Over on the Future Chips blog, Aater Suleman argues
that while(1)
can make parallel code better. Whilst I agree that the code
using while(1)
is simpler than the original in terms of
analysing the lock patterns, it achieves this by testing the logical
condition inside the while
and
using break
. This is additional, unnecessary,
complexity.
What is wanted instead is a way of encapsulating the locking, so that the loop logic is simple, and yet the lock logic is also clear.
Here is the original code from the blog post:
lock_acquire(lock); while(check_condition()){ lock_release(lock); //do any actual work in the iteration - Thanks to Caleb for this comment lock_acquire(lock); } lock_release(lock);
The implication here is that check_condition()
must be
called with the lock held, but the lock need not be held for the
actual iteration work. The code thus acquires and releases the mutex
in two places, which is unnecessary duplication, and a potential
source of errors — if the loop exits early then the lock may
be released twice, for example.
Rather than moving the condition check into the loop to avoid this duplication, a better solution is to move the lock acquisition and release into the condition check:
bool atomic_check_condition() { lock_acquire(lock); bool result=check_condition(); lock_release(lock); return result; } while(atomic_check_condition()){ //do any actual work in the iteration - Thanks to Caleb for this comment }
This gives us the best of both worlds: the lock is now held only
across the check_condition()
call, but the logic of
the while
loop is still clear.
If you're programming in C++, then the C++0x library allows us to
make atomic_check_condition()
even simpler by
using lock_guard
as in the code below, but extracting
the function is always an improvement.
bool atomic_check_condition() { std::lock_guard<mutex_type> guard(lock); return check_condition(); }
Posted by Anthony Williams
[/ threading /] permanent link
Tags: multithreading, concurrency, locks
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.
Just::Thread now supports GCC on Windows and MacOSX
Tuesday, 14 June 2011
I am pleased to announce that support for
the TDM port of gcc 4.5.2
for Windows and the MacPorts
builds of gcc 4.3, 4.4 and 4.5 have now been added
to just::thread
.
This release thus greatly improves the portability of the
library. You can now write code
using just::thread
that will work across Windows, Linux and MacOSX. With gcc 4.5
support across all 3 platforms, you can take advantage of the
extensive C++0x language support from that compiler too, including
lambda functions, rvalue references and variadic templates.
Get your copy now and add portability to your multithreaded programs.
Posted by Anthony Williams
[/ news /] permanent link
Tags: just::thread, cplusplus, multithreading, gcc, windows, macosx
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.
just::thread C++0x Thread Library V1.6 (FDIS Edition) Released
Wednesday, 25 May 2011
I am pleased to announce that version 1.6 (the FDIS edition)
of just::thread
,
our C++0x Thread Library
has just been released.
If you're interested in C++0x, I'm sure you're aware that the C++0x Final Draft International Standard (FDIS) was voted out at the last C++ Standards Committee meeting. See Michael Wong's blog post and Herb Sutter's blog post if you've been hiding under a rock for the last two months.
Anyway, after the vote at the meeting, the FDIS itself was
published in April, and just::thread
has now been
updated to match the FDIS as close as possible. Where there have
been changes to names (such
as std::chrono::system_clock::to_time_point
becoming std::chrono::system_clock::from_time_t
)
the old names have been kept, though they are marked "deprecated"
using compiler annotations.
Changes include:
- Support for gcc 4.6 on Ubuntu Natty (using the packages from the Ubuntu Toolchain PPA) and Fedora 15.
- Support for thread-local variables with non-trivial constructors
and destructors using
the
JSS_THREAD_LOCAL
macro in place of the newthread_local
keyword (which is not supported in any current compilers) . - The
std::hash<std::thread::id>
specialization has been added. - The new
constexpr
andnoexcept
keywords are used where supported (gcc 4.6 in -std=c++0x mode.) - The return type of lambda functions is correctly deduced
in
std::async
in both gcc 4.5 and 4.6 and MSVC 2010. - Various optimizations, including reduction in thread creation
code and the overhead
of
std::async
. - Added std::chrono::system_clock::from_time_t
in place
of
std::chrono::system_clock::to_time_point
.
As usual, existing customers are entitled to a free upgrade to V1.6.0 from all earlier versions.
Posted by Anthony Williams
[/ news /] permanent link
Tags: multithreading, concurrency, 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.
Picking Patterns for Parallel Programs; slides from ACCU 2011
Monday, 18 April 2011
On Saturday, I presented on Picking Patterns for Parallel Programs at ACCU 2011. We were in the Wolvercote room again, which was packed out — people sat on the floor when the chairs ran out.
I thoroughly enjoyed it (even with the minor technical issues), and I've had great feedback from several people who said it was really useful to them — Dmitry even posted on twitter that it was the "best tech talk".
The slides are available for download. The 50% discount on Just::thread mentioned at the end is only valid until 23rd April 2011.
Posted by Anthony Williams
[/ news /] permanent link
Tags: concurrency, parallelism, threading, accu
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.
Copying Exceptions in C++0x
Tuesday, 15 March 2011
One of the new features of C++0x is the ability to capture
exceptions in a std::exception_ptr
and rethrow them later
without knowing what type they are. This is particularly
useful, as it allows you to propagate the exceptions across threads
— you capture the exception in one thread, then pass the
std::exception_ptr
object across to the other thread, and
then use std::rethrow_exception()
on that other thread to
rethrow it. In fact, the exception propagation facilities
of std::async
, std::promise
and std::packaged_task
are build on this feature.
To copy or not to copy
The original proposal for the feature required that the exception
was copied when it was captured
with std::current_exception
, but under pressure from
implementors that use
the "Itanium
ABI" (which is actually used for other platforms too, such as
64-bit x86 linux and MacOSX), the requirement was lessened to allow
reference counting the exceptions instead. The problem they cited
was that the ABI didn't store the copy constructor for exception
objects, so when you called std::current_exception()
the information required to copy the object was not present.
Race conditions
Unfortunately, no-one foresaw that this would open the door for race conditions, since the same exception object would be active on multiple threads at once. If any of the thread modified the object then there would be a data race, and undefined behaviour.
It is a common idiom to catch exceptions by non-const reference in
order to add further information to the exception, and then rethrow
it. If this exception came from another thread (e.g. through use
of std::async
), then it may be active in multiple
threads at once if it was propagated
using std::shared_future
, or even just
with std::exception_ptr
directly. Modifying the
exception to add the additional information is thus a data race if
done unsynchronized, but even if you add a mutex to the class you're
still modifying an exception being used by another thread, which is
just wrong.
Race conditions are bad enough, but these race conditions are implementation-dependent. The draft allows for the exceptions to be copied (as originally intended), and some compilers do that (e.g. MSVC 2010), and it also allows for them to be reference counted, and other compilers do that (e.g. gcc 4.5 on linux). This means that code that is well-defined and race-condition-free on MSVC 2010 might be buggy, and have data races when compiled with gcc 4.5, but the compiler will not (and cannot) warn about it. This is the nastiest of circumstances — race conditions silently added to working code with no warning.
Dealing with the issue
BSI raised an issue on the FCD about this when it came to ballot time. This issue is GB-74, and thus must be dealt with one way or the other before the C++0x standard is published (though sadly, "being dealt with" can mean that it is rejected). This is being dealt with by LWG, so is also listed as LWG issue 1369, where there is a more complete proposed resolution. Unfortunately, we still need to convince the rest of the committee to make this change, including those implementors who use the Itanium ABI.
Extending the ABI
Fortunately, the Itanium ABI is designed to be extensible in a
backwards-compatible manner. This means that existing code compiled
with an existing compiler can be linked against new code compiled
with a new compiler, and everything "just works". The old code only
uses the facilities that existed when it was written, and the new
code takes advantage of the new facilities. This means that the
exception structures can be enhanced to add the necessary
information for copying the exception (the size of the object, so
we can allocate memory for it, and the address copy constructor, or
a flag to say "use memcpy
".) This isn't quite perfect,
as exceptions thrown from old code won't have the new information,
but provided we can detect that scenario all is well, as the
standard draft allows us to throw std::bad_exception
in that case.
I have written a patch for gcc 4.5.0 which demonstrates this as a proof of concept.
This patch extends the exception structures as allowed by the ABI
to add two fields: one for the object size, and one for the copy
constructor. Exceptions thrown by old code will have a size of zero
(which is illegal, so acts as a flag for old code), and thus will be
captures as std::bad_exception
when stored in
a std::exception_ptr
. Trivially copyable objects such
as a plain int
, or a POD class
will have
a NULL
copy constructor pointer but a valid size,
indicating that they are to be copied using memcpy
.
To use the patch, get the sources for gcc 4.5.0 from your
local GCC mirror,
unpack them, and apply the patch. Then compile the patched sources
and install your new gcc somewhere. Now, when you compile code that
throws exceptions it will use the
new __cxa_throw_copyable
function in place of the
old __cxa_throw
function to store the requisite
information. Unless you link against the right support code then
your applications won't link; I found I had to use
the -static
command line option to force the use of the
new exception-handling runtime rather than the standard platform
runtime.
/opt/newgcc/bin/g++ -std=c++0x -static foo.cpp -o foo
Note that if the copy constructor of the exception is not thread
safe then there might still be an issue when
using std::exception_ptr
, as my patch doesn't include a
mutex. However, this would be an easy extension to make now the
proof of concept has been done. I also expect that there are cases
that don't behave quite right, as I am far from being an expert on
the gcc internals.
Hopefully, this proof of concept will help convince the rest of the C++ committee to accept GB-74 at the meeting in Madrid next week.
Posted by Anthony Williams
[/ cplusplus /] permanent link
Tags: C++, C++0x, WG21, Exceptions, Copying, exception_ptr, rethrow_exception
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.
just::thread C++0x Thread Library V1.5.0 Released
Friday, 04 February 2011
I am pleased to announce that version 1.5.0
of just::thread
,
our C++0x Thread Library
has just been released.
This release heralds official support for Debian Lenny and Squeeze, and Fedora 13 and 14; no longer are Linux developers restricted to Ubuntu.
This version has also been updated to match the latest C++ working draft. The resultant changes are:
- There is a new launch policy
for
std::async
:std::launch::deferred
. This replacesstd::launch::sync
, and indicates that the supplied function should be run in the thread that callsget()
orwait()
on the resultant future rather than asynchronously on its own thread.std::launch::sync
is still supported for backwards compatibility. - There is a new clock type:
std::chrono::steady_clock
. This replacesstd::chrono::monotonic_clock
, and is guaranteed to be continuously increasing at a steady rate. This is the clock used for duration-based timeouts.std::chrono::monotonic_clock
is till supported for backwards compatibility. std::atomic_future
has been removed from the standard draft. It is therefore deprecated injust::thread
, though still supported for backwards compatibility.std::future
has a new member functionshare()
for easy conversion tostd::shared_future
. This works well with the new C++0x use of auto, when you know you want to get astd::shared_future
from astd::promise
,std::packaged_task
orstd::async
call:int some_function(); std::shared_future<int> f(std::async(some_function)); // old syntax auto f2=std::async(some_function).share(); // new syntax
This release also provides support
for std::atomic<char16_t>
and std::atomic<char32_t>
,
where char16_t
and char32_t
are provided
by the underlying platform.
Purchase your copy and get started with the C++0x thread library now.
As usual, existing customers are entitled to a free upgrade to V1.5.0 from all earlier versions.
Posted by Anthony Williams
[/ news /] permanent link
Tags: multithreading, concurrency, 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.
Happy New Year 2011
Thursday, 13 January 2011
It's nearly two weeks into 2011 already (though it only seems a couple of days — where did it all go?), but I'd like to wish you all a (slightly belated) Happy New Year!
2010 was a good year for me. Sales of Just::Thread
, my
implementation of the C++0x
thread library have been growing steadily — there's a new
version due out any day now, with support for the changes
accepted at the November 2010 C++ Standards meeting, and Just::Thread Pro is in the
works. I also presented
at the ACCU conference for the third year running.
It's also been a big year for the C++ community:
- the C++0x FCD was published, and we're now in the final phase of getting it ready for publication this year;
- Microsoft Visual Studio 2010 was released, providing Windows developers access to several C++0x features such as rvalue references and lambda functions;
- g++ 4.5 was released, providing further C++0x support (including lambdas, again) to C++ developers across the wide variety of platforms supported by gcc;
- Plus, of course, new versions of other compilers and libraries too (including four(!) releases of the Boost C++ libraries).
Popular articles
As is my custom, here's a list of the 10 most popular articles and blog entries from the Just Software Solutions website in 2010. The key difference from last year's list is the rise of the C++0x thread library stuff.
- November
2010 C++ Standards Committee Mailing
My summary of the November 2010 C++ committee mailing. - Implementing
a Thread-Safe Queue using Condition Variables
A description of the issues around writing a thread-safe queue, with code. - just::thread
C++0x Thread Library V1.0 Released
This is the release announcement for ourjust::thread
C++0x thread library. - Importing
an Existing Windows XP Installation into VirtualBox
This article describes how I recovered the hard disk of a dead laptop to run as a VM under VirtualBox. - Deadlock
Detection with just::thread
This article describes how to use the special deadlock-detection mode of ourjust::thread
C++0x thread library to locate the cause of deadlocks. - Implementing
drop-down menus in pure CSS (no JavaScript)
How to implement drop-down menus in CSS in a cross-browser fashion (with a teensy bit of JavaScript for IE). - Multithreading
in C++0x part 1: Starting Threads
This is the first part of my series on the new C++0x thread library. Links to the remaining parts are at the end of the article. - Thread
Interruption in the Boost Thread Library
A description of the thread interruption feature of the Boost Thread library. - Introduction
to C++ Templates
My basic introduction to C++ templates. - October 2010 C++ Standards Committee Mailing
My summary of the October 2010 C++ committee mailing, and the big issues for discussion at the November 2010 meeting — implicit move functions andnoexcept
for destructors.
What's coming in 2011?
Will 2011 be even better than 2010? I hope so. As I already
mentioned, there's a new version of just::thread
coming
soon, along with Just::Thread Pro. Also,
both the C++0x standard and my book should finally be
published. I'll also be presenting at ACCU 2011 in April —
hope to see you there.
What are you looking forward to in 2011?
Posted by Anthony Williams
[/ news /] permanent link
Tags: popular, articles
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.
November 2010 C++ Standards Committee Mailing
Tuesday, 07 December 2010
The November 2010 mailing for the C++ Standards Committee was published last week. This is the post-meeting mailing for the November 2010 committee meeting.
As well as the usual core and library issues lists, this mailing also includes an updated summary of the status of the FCD comments, along with a whole host of papers attempting to address some the remaining FCD comments and a new C++0x working draft.
To move or not to move
In my blog post on the October mailing, I mentioned that the implicit generation of move constructors was a big issue. I even contributed a paper with proposed wording for removing implicit move generation from the draft — with expert core wording guidance from Jason Merrill, this became N3216. My paper was just to give the committee something concrete to vote on — it doesn't matter how good your arguments are; if there isn't a concrete proposal for wording changes then the committee can't vote on it. In the end, the decision was that implicit move generation was a good thing, even though there was the potential for breaking existing code. However, the conditions under which move operations are implicitly generated have been tightened: the accepted proposal was N3203: Tightening the conditions for generating implicit moves by Jens Maurer, which provides wording for Bjarne's paper N3201: Moving Right Along. The proposal effectively treats copy, move and destruction as a group: if you specify any of them manually then the compiler won't generate any move operations, and if you specify a move operation then the compiler won't generate a copy. For consistency and safety, it would have been nice to prevent implicit generation of copy operations under the same circumstances, but for backwards compatibility this is still done when it would be done under C++03, though this is deprecated if the user specifies a destructor or only one of the copy operations.
Exceptions and Destructors
The second big issue from the
October mailing was the issue of implicitly adding
noexcept
to destructors. In the end, the committee went
for Jens Maurer's paper N3204:
Deducing "noexcept" for destructors — destructors have the
same exception specification they would have if they were implicitly
generated, unless the user explicitly says otherwise. This will break
code, but not much — the fraction of code that intentionally
throws an exception from a destructor is small, and easily annotated
with noexcept(false)
to fix it.
Concurrency-related papers
There are 9 concurrency-related papers in this mailing, which I've summarised below. 8 of them were adopted at this meeting, and are now in the new C++0x working draft.
- N3188 - Revision to N3113: Async Launch Policies (CH 36)
This paper is a revision of N3113 from the August mailing. It is a minor revision to the previous paper, which clarifies and simplifies the proposed wording.
It provides a clearer basis for implementors to supply additional launch policies for
std::async
, or for the committee to do so in a later revision of the C++ standard, by making thestd::launch
enum a bitmask type. It also drops thestd::launch::any
enumeration value, and renamesstd::launch::sync
tostd::launch::deferred
, as this better describes what it means.The use of a bitmask allows new values to be added which are either distinct values, or combinations of the others. The default policy for
std::async
is thusstd::launch::async|std::launch::deferred
.- N3191: C++ Timeout Specification
This paper is a revision of N3128: C++ Timeout Specification from the August mailing. It is a minor revision to the previous paper, which clarifies and simplifies the proposed wording.
There are several functions in the threading portion of the library that allow timeouts, such as the
try_lock_for
andtry_lock_until
member functions of the timed mutex types, and thewait_for
andwait_until
member functions of the future types. This paper clarifies what it means to wait for a specified duration (with the xxx_for
functions), and what it means to wait until a specified time point (with the xxx_until
functions). In particular, it clarifies what can be expected of the implementation if the clock is changed during a wait.This paper also proposes replacing the old
std::chrono::monotonic_clock
with a newstd::chrono::steady_clock
. Whereas the only constraint on the monotonic clock was that it never went backwards, the steady clock cannot be adjusted, and always ticks at a uniform rate. This fulfils the original intent of the monotonic clock, but provides a clearer specification and name. It is also tied into the new wait specifications, since waiting for a duration requires a steady clock for use as a basis.- N3192: Managing C++ Associated Asynchronous State
This paper is a revision of N3129: Managing C++ Associated Asynchronous State from the August mailing. It is a minor revision to the previous paper, which clarifies and simplifies the proposed wording.
This paper tidies up the wording of the functions and classes related to the future types, and clarifies the management of the associated asynchronous state which is used to communicate e.g. between a
std::promise
and astd::future
that will receive the result.- N3193: Adjusting C++ Atomics for C Compatibility
This paper is an update to N3164: Adjusting C++ Atomics for C Compatibility from the October mailing.
It drops the C compatibility header
<stdatomic.h>
, and the macro_Atomic
, and loosens the requirements on theatomic_xxx
types — they may be base classes of the associatedatomic<T>
specializations, or typedefs to them.- N3194: Clarifying C++ Futures
This paper is a revision ofN3170: Clarifying C++ Futures from the October mailing.
There were a few FCD comments from the US about the use of futures; this paper outlines all the issues and potential solutions. The proposed changes are actually fairly minor though:
-
future
gains ashare()
member function for easy conversion to the correspondingshared_future
type; - Accessing a
shared_future
for whichvalid()
isfalse
is now encouraged to throw an exception though it remains undefined behaviour; atomic_future
is to be removed;packaged_task
now has avalid()
member function instead ofoperator bool
for consistency with the future types.
A few minor changes have also been made to the wording to make things clearer.
-
- N3196: Omnibus Memory Model and Atomics Paper
This paper is an update to N3125: Omnibus Memory Model and Atomics Paper from the August mailing.
This paper clarifies the wording surrounding the memory model and atomic operations.
- N3197: Lockable Requirements for C++0x
This paper is an update to N3130: Lockable Requirements for C++0x from the October mailing. This is a minor revision reflecting discussions at Batavia.
This paper splits out the requirements for general lockable types away from the specific requirements on the standard mutex types. This allows the lockable concepts to be used to specify the requirements on a type to be used the the
std::lock_guard
andstd::unique_lock
class templates, as well as for the various overloads of the wait functions onstd::condition_variable_any
, without imposing the precise behaviour ofstd::mutex
on user-defined mutex types.- N3209: Progress guarantees for C++0x (US 3 and US 186)(revised)
This paper is a revision ofN3152: Progress guarantees for C++0x (US 3 and US 186) from the October mailing. It is a minor revision to the previous paper, which extends the proposed wording to cover
compare_exchange_weak
as well astry_lock
.The FCD does not make any progress guarantees when multiple threads are used. In particular, writes made by one thread do not ever have to become visible to other threads, and threads aren't guaranteed ever to actually run at all. This paper looks at the issues and provides wording for minimal guarantees.
- N3230: Constexpr Library Additions: future
This paper has not yet been accepted by the committee. It adds constexpr to the default constructors of
future
andshared_future
, so that they can be statically initialized.
Other adopted papers
Of course, the committee did more than just address implicit move, exceptions in destructors and concurrency. The full minutes are available as N3212 in the mailing. Here is a quick summary of some of the other changes made:
- Library functions that don't throw exceptions have been changed to
use
noexcept
- The ratio arithmetic facilities have been changed to allow
libraries to try and give the correct result if the result is
representable, but the intermediate calculations may overflow
(e.g.
ratio_add<ratio<1,INTMAX_MAX>,ratio<1,INTMAX_MAX>>
) (N3210) - New functions have been added to retrieve the current new handler, terminate handler or unexpected handler (N3189)
- Alignment control is now done with the
alignas
keyword, rather than an attribute (N3190) - Virtual function override control is now done with keywords
(including the first context sensitive keywords:
override
amdfinal
) rather than attributes (N3206)
For the remaining changes, see the full minutes.
FCD comment status
The count of unresolved FCD comments is dropping rapidly, and now stands at 75 (out of 564 total), of which only 56 have any technical content. See N3224: C++ FCD Comment Status from the mailing for the full list.
Your comments
If you have any opinions on any of the papers listed here, or the resolution of any NB comments, please add them to the comments for this post.
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-2025 Just Software Solutions Ltd. All rights reserved. | Privacy Policy