Blog Archive for / 2010 / 02 /
February 2010 C++ Standards Committee Mailing
Tuesday, 23 February 2010
The February 2010 mailing for the C++ Standards Committee was published last week. This is the pre-meeting mailing for the March 2010 committee meeting and contains a new working draft.
There are 5 concurrency-related papers (of which my name is on one), which I summarize below:
Concurrency-related papers
- N3038:
Managing the lifetime of
thread_local
variables with contexts (Revision 2) This is my paper on creating contexts for
thread_local
variables. The use of such contexts allows you to control when variables that are declared asthread_local
are destroyed. It is a revision of my previous paper N2959; the primary change is that contexts can now be nested, which allows library code to use them without having to know whether or not a context is currently active.- N3040: Various threads issues in the library (LWG 1151)
This paper by Hans Boehm seeks to address LWG issue 1151. The key issue is to ensure that it is clear which operations may constitute a data race if they run concurrently without synchronization.
- N3041: Futures and Async Cleanup
The adoption of multiple papers affecting futures and
std::async
at the same C++ committee meeting meant that the wording ended up being unclear. Detlef Vollmann kindly volunteered to write a paper to resolve these issues, and this is it.Unfortunately, I think that some of the wording is still unclear. I also dislike Detlef's proposal to force the
wait_for
andwait_until
member functions of the future types to throw exceptions if the future was created from a call tostd::async
with a launch policy ofstd::launch::sync
. My preferred alternative is to change the return type frombool
to an enumeration with distinct values for if the future is ready, if the wait timed out, or if the future holds a deferred function fromstd::launch::sync
that has not yet started. This would be similar to the current behaviour ofstd::condition_variable::wait_for
andstd::condition_variable::wait_until
, which return astd::cv_status
enumeration value.- N3042:
Renaming
launch::any
and what asyncs really might be This is another paper from Detlef Vollmann proposing renaming
std::launch::any
tostd::launch::any_sync
. His rationale is that future revisions of the C++ standard may wish to add values to thestd::launch
enumeration for additional types of async calls that should not be covered bystd::launch::any
. Personally, I think this is a non-issue, and should be covered as and when such values are added.- N3045: Updates to C++ Memory Model Based on Formalization
Following attempts to create a mathematical formalization of the memory model it became clear that some cases were unclear or ambiguous or did not guarantee the desired semantics. This paper proposes some changes to the wording of the memory model in order to ensure that it means what we intended it to mean.
Other Papers
There's several non-concurrency papers in the mailing as well as the standard set (working draft, agenda, issues lists, etc.). The most significant of these in my view is N3044 which proposes compiler-defined move constructors and assignment operators. Check the mailing for the full set.
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.
The difference between struct and class in C++
Sunday, 21 February 2010
I've seen a lot of people asking about the differences
between the use of the struct
and class
keywords in C++ lately. I don't know whether there's an influx of
C++ programmers due to the upcoming C++0x standard, or whether I've
just noticed people asking questions that haven't caught my eye
before. Whatever the reason, I'm writing this blog entry as
something I can point to the next time someone asks the
question.
Declaring and defining user-defined types
The primary use of both the struct
and class
keywords is to define a user-defined type. In
C++, such a user-defined type is termed a "class" regardless of
which keyword is used in the definition. The choice of keyword is in
one sense arbitrary, since the same features and facilities are
available whichever keyword is used — there is only one
semantic difference which we shall look at shortly. The following
two class definitions are thus equivalent in all respects apart from
the names of the classes:
struct type_a { private: int data; public: type_a(int data_): data(data_) {} virtual void foo()=0; virtual ~type_a() {} }; class type_b { private: int data; public: type_b(int data_): data(data_) {} virtual void foo()=0; virtual ~type_b() {} };
As this little example shows, you can have constructors,
destructors, member functions, private members and even virtual
member functions in a class declared with the struct
keyword, just as you can with a class declared using
the class
keyword. Though this example doesn't show it,
you can also use the struct
keyword to declare classes
with base classes.
You can even forward-declare your class using one keyword and then define it with the other, though compilers have been known to complain about this usage:
struct foo; class foo {}; class bar; struct bar {};
So, what of the minor semantic difference then? The change is in
the default access specifier for members and base
classes. Though classes defined using either keyword can
have public
, private
and protected
base classes and members, the default
choice for classes defined using class
is private
, whilst for those defined
using struct
the default is public
. This
is primarily for backwards compatibility with C: the members of a C
structure can be freely accessed by all code so in order to allow
existing C code to compile unchanged as C++ the default access
specifier for members of a class declared with struct
must be public
. On the other hand, private data is a
key aspect of the encapsulation aspect of object-oriented design, so
this is the default for those classes declare
with class
.
C doesn't have inheritance, but the default access specifier for
base classes varies with the keyword used to declare the derived
class too. It is public
for classes declared
with struct
and private
for those declared
with class
just the same as for data members. You can
still override it with an explicit specifier in both cases.
Let's take a quick look at some examples to see how that works:
struct s1 { int a; // public private: int b; // private protected: int c; // protected public: int d; // public again }; class c1 { int a; // private private: int b; // still private protected: int c; // protected public: int d; // public }; struct s2: s1, // public private c1, // private type_b, // public again protected foo, // protected public bar // public again {}; class c2: s1, // private private c1, // still private type_b, // private again protected foo, // protected public bar // public {};
As far as declaring and defining user-defined types in C++, that is
the only difference; in all other respects, classes declared
with struct
are identical to those declared
with class
.
C Compatibility
We touched on this a bit earlier: classes declared with
the struct
keyword can be compiled as C if they don't
use any features that are C++ specific. Thus the following is both a
valid C++ class and a valid C structure:
struct c_compatible { int i; char c; double d; };
It is therefore common to see struct
used in header
files that are shared between C and C++. Since non-virtual member
functions don't affect the class layout you can even have member
functions in such a type, provided they are hidden from the C
compiler with a suitable #ifdef
:
struct baz { int i; #ifdef __cplusplus void foo(); #endif; };
Templates
There is one place where you can use the class
keyword
but not the struct
one, and that is in the declaration
of a template. Template type parameters must be declared using
either the class
or typename
keyword; struct
is not allowed. The choice
of class
or typename
in this case is again
arbitrary — the semantics are identical. The choice of keyword
does not impose any semantic meaning, any type (whether a built in
type like int
or a user-defined type like a class or
enumeration) can be used when instantiating the template in either
case.You can of course declare a class template with
the struct
keyword, in which case the default access
for the members of the template is public
.
template<class T> // OK void f1(T t); template<typename T> // OK void f2(T t); template<struct T> // ERROR, struct not allowed here void f3(T t); template<class T> struct S { T x; // public member };
That's all folks!
These are the only concrete distinctions between the uses of
the struct
keyword and the class
keyword
in C++. People also use them for documentation purposes,
reserving struct
for C-compatible classes, or classes
with no member functions, or classes with no private data, or
whatever their coding standard says. However, this is just
documentation and convention rather than an inherent difference: you
could use struct
for all your classes,
or class
for all your classes except those that are
shared with C.
Posted by Anthony Williams
[/ cplusplus /] permanent link
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.
Multithreading in C++0x part 8: Futures, Promises and Asynchronous Function Calls
Thursday, 11 February 2010
This is the eighth in a series of blog posts introducing the new C++0x thread library. See the end of this article for a full set of links to the rest of the series.
In this installment we'll take a look at the "futures" mechanism from C++0x. Futures are a high level mechanism for passing a value between threads, and allow a thread to wait for a result to be available without having to manage the locks directly.
Futures and asynchronous function calls
The most basic use of a future is to hold the result of
a call to the new std::async
function for running some code
asynchronously:
#include <future> #include <iostream> int calculate_the_answer_to_LtUaE(); void do_stuff(); int main() { std::future<int> the_answer=std::async(calculate_the_answer_to_LtUaE); do_stuff(); std::cout<<"The answer to life, the universe and everything is " <<the_answer.get()<<std::endl; }
The call to std::async
takes care of creating a thread, and
invoking calculate_the_answer_to_LtUaE
on that
thread. The main thread can then get on with
calling do_stuff()
whilst the immensely time consuming
process of calculating the ultimate answer is done in the
background. Finally, the call to the get()
member
function of the std::future<int>
object then
waits for the function to complete and ensures that the necessary
synchronization is applied to transfer the value over so the main
thread can print "42".
Sometimes asynchronous functions aren't really asynchronous
Though I said that std::async
takes care of creating a
thread, that's not necessarily true. As well as the function being
called, std::async
takes a launch policy which
specifies whether to start a new thread or create a "deferred
function" which is only run when you wait for it. The default launch
policy for std::async
is std::launch::any
,
which means that the implementation gets to choose for you. If you
really want to ensure that your function is run on its own thread
then you need to specify the std::launch::async
policy:
std::future<int> the_answer=std::async(std::launch::async,calculate_the_answer_to_LtUaE);
Likewise, if you really want the function to be executed in
the get()
call then you can specify
the std::launch::sync
policy:
std::future<int> the_answer=std::async(std::launch::sync,calculate_the_answer_to_LtUaE);
In most cases it makes sense to let the library choose. That way you'll avoid creating too many threads and overloading the machine, whilst taking advantage of the available hardware threads. If you need fine control, you're probably better off managing your own threads.
Divide and Conquer
std::async
can be used to easily parallelize simple algorithms. For example,
you can write a parallel version of for_each
as
follows:
template<typename Iterator,typename Func> void parallel_for_each(Iterator first,Iterator last,Func f) { ptrdiff_t const range_length=last-first; if(!range_length) return; if(range_length==1) { f(*first); return; } Iterator const mid=first+(range_length/2); std::future<void> bgtask=std::async(¶llel_for_each<Iterator,Func>, first,mid,f); try { parallel_for_each(mid,last,f); } catch(...) { bgtask.wait(); throw; } bgtask.get(); }
This simple bit of code recursively divides up the range into
smaller and smaller pieces. Obviously an empty range doesn't require
anything to happen, and a single-point range just requires
calling f
on the one and only value. For bigger ranges
then an asynchronous task is spawned to handle the first half, and
then the second half is handled by a recursive
call.
The try
- catch
block just ensures that
the asynchronous task is finished before we leave the function even
if an exception in order to avoid the background tasks potentially
accessing the range after it has been destroyed. Finally,
the get()
call waits for the background task, and propagates any
exception thrown from the background task. That way if an exception
is thrown during any of the processing then the calling code will
see an exception. Of course if more than one exception is thrown
then some will get swallowed, but C++ can only handle one exception
at a time, so that's the best that can be done without using a
custom composite_exception
class to collect them
all.
Many algorithms can be readily parallelized this way, though you may want to have more than one element as the minimum range in order to avoid the overhead of spawning the asynchronous tasks.
Promises
An alternative to
using std::async
to spawn the task and return the future is to manage the threads
yourself and use
the std::promise
class template to provide the
future. Promises provide a basic mechanism for transferring values
between threads:
each std::promise
object is associated with a
single std::future
object. A thread with access to
the std::future
object can use wait for the result to be set, whilst another thread
that has access to the
corresponding std::promise
object can
call set_value()
to store the value and make the future ready. This works
well if the thread has more than one task to do, as information can
be made ready to other threads as it becomes available rather than
all of them having to wait until the thread doing the work has
completed. It also allows for situations where multiple threads
could produce the answer: from the point of view of the waiting
thread it doesn't matter where the answer came from, just that it is
there so it makes sense to have a single future to represent that
availability.
For example, asynchronous I/O could be modelled on a promise/future basis: when you submit an I/O request then the async I/O handler creates a promise/future pair. The future is returned to the caller, which can then wait on the future when it needs the data, and the promise is stored alongside the details of the request. When the request has been fulfilled then the I/O thread can set the value on the promise to pass the value back to the waiting thread before moving on to process additional requests. The following code shows a sample implementation of this pattern.
class aio { class io_request { std::streambuf* is; unsigned read_count; std::promise<std::vector<char> > p; public: explicit io_request(std::streambuf& is_,unsigned count_): is(&is_),read_count(count_) {} io_request(io_request&& other): is(other.is), read_count(other.read_count), p(std::move(other.p)) {} io_request(): is(0),read_count(0) {} std::future<std::vector<char> > get_future() { return p.get_future(); } void process() { try { std::vector<char> buffer(read_count); unsigned amount_read=0; while((amount_read != read_count) && (is->sgetc()!=std::char_traits<char>::eof())) { amount_read+=is->sgetn(&buffer[amount_read],read_count-amount_read); } buffer.resize(amount_read); p.set_value(std::move(buffer)); } catch(...) { p.set_exception(std::current_exception()); } } }; thread_safe_queue<io_request> request_queue; std::atomic_bool done; void io_thread() { while(!done) { io_request req=request_queue.pop(); req.process(); } } std::thread iot; public: aio(): done(false), iot(&aio::io_thread,this) {} std::future<std::vector<char> > queue_read(std::streambuf& is,unsigned count) { io_request req(is,count); std::future<std::vector<char> > f(req.get_future()); request_queue.push(std::move(req)); return f; } ~aio() { done=true; request_queue.push(io_request()); iot.join(); } }; void do_stuff() {} void process_data(std::vector<char> v) { for(unsigned i=0;i<v.size();++i) { std::cout<<v[i]; } std::cout<<std::endl; } int main() { aio async_io; std::filebuf f; f.open("my_file.dat",std::ios::in | std::ios::binary); std::future<std::vector<char> > fv=async_io.queue_read(f,1048576); do_stuff(); process_data(fv.get()); return 0; }
Next Time
The sample code above also demonstrates passing exceptions between
threads using
the set_exception()
member function
of std::promise
. I'll
go into more detail about exceptions in multithreaded next time.
Subscribe
to the RSS feed
or email
newsletter for this blog to be sure you don't miss the rest of the
series.
Try it out
If you're using Microsoft Visual Studio 2008 or g++ 4.3 or 4.4 on
Ubuntu Linux you can try out the examples from this series using our
just::thread
implementation of the new C++0x thread library. Get your copy
today.
Multithreading in C++0x Series
Here are the posts in this series so far:
- Multithreading in C++0x Part 1: Starting Threads
- Multithreading in C++0x Part 2: Starting Threads with Function Objects and Arguments
- Multithreading in C++0x Part 3: Starting Threads with Member Functions and Reference Arguments
- Multithreading in C++0x Part 4: Protecting Shared Data
- Multithreading
in C++0x Part 5: Flexible locking
with
std::unique_lock<>
- Multithreading in C++0x part 6: Lazy initialization and double-checked locking with atomics
- Multithreading in C++0x part 7: Locking multiple mutexes without deadlock
- Multithreading in C++0x part 8: Futures, Promises and Asynchronous Function Calls
Posted by Anthony Williams
[/ threading /] permanent link
Tags: concurrency, multithreading, C++0x, thread, future, promise, async
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