Blog Archive

Memories of Learning C

Monday, 17 October 2011

Herb Sutter's latest blog entry invites us to share our memories of our first C program, in tribute to Dennis Ritchie. I can't remember what my first C program was, but I thought I'd write about my memories of learning C.

I studied Physics at college, and there was very little programming taught as part of the course. That didn't bother me though; I'd taught myself to program up until then, and I wasn't going to stop now. The big benefit I got from computing at college was access to the internet, and access to C and C++ compilers. I could program in BASIC, Pascal and a couple of forms of assembly language, and I'd eagerly read Stan Lippman's C++ Primer and written out (on paper!) some C++ code, but I hadn't yet had a C++ compiler to try out my programs on.

I wrote several C++ programs before I even considered writing a plain C program, but I probably typed in and compiled the classic printf("hello world\n"); C program to check everything was working before I compiled any C++.

Usenet

My strongest memories about learning C are about learning from usenet. Though I had access to C compilers at college, access to experts was not so readily available unless you were studying computing. With access to the internet, I didn't need local experts though — usenet provided access to experts from across the world. I read comp.lang.c and comp.lang.c++ avidly, and taught myself both languages together. The usenet community was invaluable to me. The wealth of knowledge that people had, and their willingness to share with newbies was something I really appreciated.

I remember struggling over file handling, and getting the arguments to scanf right; I remember puzzling over the poor performance of a program and having someone kindly point out that my code was doing malloc and free calls in a tight loop. Though I tend to answer more questions than I ask these days, I still hang out on newgroups such as comp.lang.c++ today. It seems that for many people StackOverflow has replaced usenet as the place to go for help, but the old-style newsgroups are still valuable.

Ubiquity

Back then, C++ compilers were in their infancy. Templates didn't work on every compiler, there was no STL, and many platforms didn't have a working C++ compiler at all. I consequently wrote a lot of C — every platform had a C compiler, and my C code would work on the college PCs, my PC (when I saved up enough to buy one), the University's Unix machine, and the Physics department workstations. The same could not be said for C++.

The ubiquity of C is something I still appreciate today, and this is only possible because Dennis Ritchie designed his language to be portable to multiple platforms. Though "implementation defined" behaviour can be frustrating when the implementation defines it a different way to how you would like, it is this that enables the portability. You want to write code for a DSP that only handles 32-bit data? Fine: make char, short, int and long all 32-bits. What if your machine has 9-bit bytes? No problem: just make char 9 bits, and everything else a convenient multiple of that.

C is the basic lingua-franca of the computing world. It is a "portable assembly language". These days I use C++ where I can because it allows a higher level of abstraction, and easier expression of intent without compromising on the performance you'd get with plain C, but it's not as portable, and wouldn't be possible without C.

The computing world owes a lot to Dennis Ritchie.

Posted by Anthony Williams
[/ general /] permanent link
Tags: ,

| Stumble It! stumbleupon logo | Submit to Reddit reddit logo | Submit to DZone dzone logo

Comment on this post

If you liked this post, why not subscribe to the RSS feed RSS feed or Follow me on Twitter? You can also subscribe to this blog by email using the form on the right.

Computer Education

Wednesday, 12 October 2011

Andrew Hague's post on Computer Education in Britain touches on something I've been discussing with my wife recently.

The travesty of ICT

Our children do not get taught anything at school about how computers work, or how to program them, and are unlikely to. Andrew says he found that "the study of computer science for British children ends at about age 11." This doesn't tally with my experience of primary schools — they are never taught any computer science. Local secondary schools are proud of their ICT suites, with office programs and image editing programs galore, but not a single class on the basics of computers and programming.

Part of the problem is the complexity of modern computers. Whereas the computers we grew up with (the Dragon 32, BBC Micro, ZX Spectrum, Commodore 64, etc.) were simple beasts, and booted into a programming environment (BASIC), modern computers are complex beasts with a swish graphical OS with no native programming environment. Yes, you can use Javascript in a browser, or the macro language in office programs, but it's not the same. PCs do not invite programming the same way that the older computers did, and you have to go out of your way to provide a basic programming environment.

Schools could overcome this hurdle, and provide programming environments, but they don't. Instead they teach everyone how to use the latest versions of office programs, despite the fact that next year's release will have a different UI, and different capabilities. Yes, children need to be computer-savvy, due to the prevalence of computers in everyday life, but they don't need to be experts in using word processors. Rather, they should be taught how to learn to use the programs, the things that are common about them (e.g. menus), how to get help (the help menu, Google), and so forth, and then taught about how computers work. Yes, use a word processor for writing the occasional thing in English, or use a spreadsheet for doing some data analysis in Geography, but the "computing" lessons should be about programming and how computers work at the basic level, rather than how to use popular software.

I think this lack of teaching about the basics of computing has a wider effect, as well as the lack of new programmers. The computer is something that people don't understand, but which they rely on. This can give people a sense of powerlessness, especially when it does something unexpected. I've had to help people who've been all in a panic because they "lost their work". It didn't appear in the list that was presented in the "open file" dialog, so it was "lost". Somehow they had saved it in a different directory, and their lack of understanding about the file system meant they didn't know how to find it, and panicked — the computer that they relied on had "lost" their important work. Teaching about the basics of modern operating systems (rather than the specifics of the software package being used) would have alleviated this fear.

Addressing the Problem

So, what is to be done? Firstly, as programming parents we can teach our children about computers and programming, which is something that my wife and I have started doing. But beyond that, we need to make the schools, colleges and government aware of the issues.

Andrew points to the Computing at School working group and the Behind the Screen project, both of which seem promising. However, without support these projects will fizzle, and our children will continue to be taught how to use office software rather than computing principles.

Posted by Anthony Williams
[/ general /] permanent link
Tags: , ,

| Stumble It! stumbleupon logo | Submit to Reddit reddit logo | Submit to DZone dzone logo

Comment on this post

If you liked this post, why not subscribe to the RSS feed RSS feed or Follow me on Twitter? You can also subscribe to this blog by email using the form on the right.

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: , ,

| Stumble It! stumbleupon logo | Submit to Reddit reddit logo | Submit to DZone dzone logo

Comment on this post

If you liked this post, why not subscribe to the RSS feed RSS feed or Follow me on Twitter? You can also subscribe to this blog by email using the form on the right.

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: ,

| Stumble It! stumbleupon logo | Submit to Reddit reddit logo | Submit to DZone dzone logo

Comment on this post

If you liked this post, why not subscribe to the RSS feed RSS feed or Follow me on Twitter? You can also subscribe to this blog by email using the form on the right.

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: , ,

| Stumble It! stumbleupon logo | Submit to Reddit reddit logo | Submit to DZone dzone logo

Comment on this post

If you liked this post, why not subscribe to the RSS feed RSS feed or Follow me on Twitter? You can also subscribe to this blog by email using the form on the right.

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: , , , , ,

| Stumble It! stumbleupon logo | Submit to Reddit reddit logo | Submit to DZone dzone logo

Comment on this post

If you liked this post, why not subscribe to the RSS feed RSS feed or Follow me on Twitter? You can also subscribe to this blog by email using the form on the right.

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 new thread_local keyword (which is not supported in any current compilers) .
  • The std::hash<std::thread::id> specialization has been added.
  • The new constexpr and noexcept 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.
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.6.0 from all earlier versions.

Posted by Anthony Williams
[/ news /] permanent link
Tags: , ,

| Stumble It! stumbleupon logo | Submit to Reddit reddit logo | Submit to DZone dzone logo

Comment on this post

If you liked this post, why not subscribe to the RSS feed RSS feed or Follow me on Twitter? You can also subscribe to this blog by email using the form on the right.

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: , , ,

| Stumble It! stumbleupon logo | Submit to Reddit reddit logo | Submit to DZone dzone logo

Comment on this post

If you liked this post, why not subscribe to the RSS feed RSS feed or Follow me on Twitter? You can also subscribe to this blog by email using the form on the right.

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: , , , , , ,

| Stumble It! stumbleupon logo | Submit to Reddit reddit logo | Submit to DZone dzone logo

Comment on this post

If you liked this post, why not subscribe to the RSS feed RSS feed or Follow me on Twitter? You can also subscribe to this blog by email using the form on the right.

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 replaces std::launch::sync, and indicates that the supplied function should be run in the thread that calls get() or wait() 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 replaces std::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 in just::thread, though still supported for backwards compatibility.
  • std::future has a new member function share() for easy conversion to std::shared_future. This works well with the new C++0x use of auto, when you know you want to get a std::shared_future from a std::promise, std::packaged_task or std::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: , ,

| Stumble It! stumbleupon logo | Submit to Reddit reddit logo | Submit to DZone dzone logo

Comment on this post

If you liked this post, why not subscribe to the RSS feed RSS feed or Follow me on Twitter? You can also subscribe to this blog by email using the form on the right.

More recent entries Older entries