Summary:
The C++ standardization committee is hard at work standardizing threads for the next version of C++. Some members recently met to discuss the issues, and The C++ Source was there. Read on to learn what the world’s leading experts on concurrency are planning for C++0x.
The ability to add new comments in this discussion is temporarily disabled.
Most recent reply: July 4, 2017 6:05 AM by
|
> > This goes beyond a particular OS's implementation of > > threading, and right down to the hardware.
> Perhaps I missing something, but wouldn't implementing > threading at the hardware level rather than through the > OS have the potential to bring the OS crashing down? How > can two entities be manipulating the same hardware > registers to different ends?
I didn't say we're "implementing threading at the hardware level." I said we're defining the semantics of C++ in terms of an abstract machine. How it's actually implemented is a problem for the compiler and OS vendors. It will work much like it does today, with the exception that the C++ standard will actually make some guarantees for correctly written multi-threaded C++ programs.
-- Eric Niebler
|
|
|
> I didn't say we're "implementing threading at the hardware > level."
You said "right down to the hardware" which certainly implies "implementing threading at the hardware level."
> How it's actually > implemented is a problem for the compiler and OS > vendors. It will work much like it does today, with the > exception that the C++ standard will actually make some > guarantees for correctly written multi-threaded C++ > programs.
So we're really back to my original point: This will be an abstraction that hides the unique threading characteristics of each OS.
This is the same problem that Java attempted to solve (although using a different approach) with mixed results.
|
|
|
> So we're really back to my original point: This will be an > abstraction that hides the unique threading > characteristics of each OS. > > This is the same problem that Java attempted to solve > (although using a different approach) with mixed results.
If I understood Eric correctly, the compiler will be able to use these OS-specific threading characteristics, but the programmer will manipulate threads at the C++ level. So if you say something like
atomic<int> x; ... y = x; ...
the compiler will "know" the unique threading characteristics of the underlying OS and will generate appropriate (and hopefully optimal) code for this.
|
|
|
> If I understood Eric correctly, the compiler will be able > to use these OS-specific threading characteristics, but > the programmer will manipulate threads at the C++ level. > So if you say something like > > atomic<int> x; > ... > y = x; > ... > > the compiler will "know" the unique threading > characteristics of the underlying OS and will generate > appropriate (and hopefully optimal) code for this.
I understand, but the core problem isn't converting from a C++ form to an OS call, but that in some cases the C++ application code will not have the same behavior when running on different OS's.
There's not a true one-to-one mapping of behavior between threading function implementations on different OS's. That means that an abstraction must either be limited to a common set of functions that behave identically on all systems (assuming that set isn't empty), a broader set with platform-dependent behavior, or a mix of the two.
One example: some operating systems use cooperative multithreading exclusively, some use preemptive multithreading exclusively and some use a combination. If you write code with a "sleep" function or "synchronization" function what is the common behavior you expect to see?
|
|
|
> > Java threading can be more efficient than you can > easily > > achieve in C++. For example the implementation of the > > synchronization primitives depends on how many CPUs are > > present at RUN TIME. The performance is much better > than > > straight forward use of the Windows critical section > > methods. > > The Windows critical section is the most limited of its > synchronization primitives in that it is only useful > within a single process. True, but it is also the fastest and in the context of threading, in process synchronization is what is required.
> optimization they do, but I would certainly be skeptical > of the idea that Java does it more efficiently. Any What Java does is use CPU atomic operations (inlined code) to test if a lock is contended, if not contended it can proceed into the critical section without executing any call to the OS. If the lock is contended then it uses the usual OS provided method to block. As most locking is usually uncontended this saves a lot of OS calls and locking is reduced to a minimal test and swap (or similar) instruction.
You can (and I have) do something similar in C++, except that you can't inline code which is depends on the number of CPU (I suppose you could generate multiple .dll's etc for the 1 and >1 cases).
I tested this ages ago (even the early Microsoft JVM used these techniques), I'm not sure if I can still dig up the code/results. The latest JVM use a lot more optimisation techniques to reduce the cost of locking.
|
|
|
> I understand, but the core problem isn't converting from a > C++ form to an OS call, but that in some cases the C++ > application code will not have the same behavior when > running on different OS's.
As well as the threading methods/classes you also require a set of rules which specify what you can assume and what you can't assume about threading behaviour. If your application sticks to the rules (and does not for example assume that thread scheduling is 'fair') then it will work correctly on any conforming implementation. What frequently goes wrong with threading in Java is that people assume that all systems behave like their own even though the documentation explicitly says that you can't make such an assumption. So the effort is not to guarantee identical behaviour for all code on all systems, but only to guarantee that code which respects the rules (the Memory Model) will work correctly on all systems. Bad code might work on some systems but not on others, but there is nothing new in that.
|
|
|
> Achilleas, > > Please Google "Boehm "Threads Cannot Be Implemented As A > Library"". In that paper, Hans describes in detail why we > can't just standardize thread and lock classes and call it > good. For those classes to actually work across platforms, > they need to be able to rely on things that the language > currently doesn't guarantee. Standardizing C++'s memory > model is the first and most important step towards > standardizing threads in C++. > > -- > Eric Niebler
But almost all C++ versions in almost all O/Ses provide threads, critical sections, mutexes and semaphores. Therefore I do not see where is the problem for the 99% of the cases.
I am not saying that what Boehm says is not true. What I am saying is that the delay to cater for very excuisite needs (like atomic access to primitives or bitfields) is seriously hurting C++'s image, (again, like with garbage collection) and prevents people from chosing it as a development language, thus hurting its development even more.
Of course in the grand scheme of things, it does not really matter, does it? there are plenty of other languages around...
|
|
|
> Nobody is trying to "turn C++ into Java." The committee is > interested in standardizing existing practice. We should > standardize threads for the simple reason that lots of > people are writing multi-threaded C++ programs today. To > not put threads in the standard would be to ingore the > needs of real C++ programmers. > > -- > Eric Niebler
And not putting garbage collection in the standard is not ignoring the needs of real C++ programmers?
I am sorry to say this, but it seems kind of hypocritical.
Many C++ programs suffer from manual memory management, and gc is a priority over threads. I have not used a single C++ application that has not crashed in one way or another, due to some wild pointer or memory leak. And using another language is simply not an option: there is no way to write programs like Firefox, Word, Powerpoint and Visio in languages other than C++, because those other languages do not allow the performance of C++.
Using multithreading currently is very easy, even if there is not a single wrapper library around: hacking together a few classes to wrap the native calls is very very easy. On the other hand, writing a proper garbage collector is impossible (and don't mention Boehm's collector, because a) it is very under-performant(without type information), b) it does not have weak pointers and other facilities).
|
|
|
> no way to write programs like Firefox, Word, Powerpoint > and Visio in languages other than C++, because those other > languages do not allow the performance of C++.
None of those applications would be in my list as requiring C++ for performance reasons. Today, all could be implemented in a number of other languages without compromising the user experience. The choice at the time those projects were started probably was more restricted.
|
|
|
> But almost all C++ versions in almost all O/Ses provide > threads, critical sections, mutexes and semaphores. > Therefore I do not see where is the problem for the 99% of > the cases.
But how do you port such code or write portable applications? The current answer seems to be that portability is restricted to the set of operating systems sufficiently like that on which it was first written.
|
|
|
> Many C++ programs suffer from manual memory management, > and gc is a priority over threads. I have not used a > single C++ application that has not crashed in one way or > another, due to some wild pointer or memory leak.
Using boost::shared_ptr (or some other kinds of smart pointers) can eliminate many (in some cases all) memory leaks. See boost.org for examples.
|
|
|
> Using boost::shared_ptr (or some other kinds of smart > pointers) can eliminate many (in some cases all) memory > leaks. See boost.org for examples.
In some other cases it eliminates very few leaks.
|
|
|
> As well as the threading methods/classes you also require > a set of rules which specify what you can assume and what > you can't assume about threading behaviour. If your > application sticks to the rules (and does not for example > assume that thread scheduling is 'fair') then it will work > correctly on any conforming implementation.
But these rules are often more restrictive, make writing threaded code more complicated, and have a higher potential for error than native methods. It's more of a step backward than forward.
>Bad code might work on some > systems but not on others, but there is nothing new in > that.
A better way to say it is that good code on one system can be bad on another, but I think there is something new about this behavior for C++. What other standard C++ functions behave significantly different on different OS's and require special rules to follow?
|
|
|
> And not putting garbage collection in the standard is not > ignoring the needs of real C++ programmers? >
No, it is not :)
Seriously, none of developers I know would ever use GC with C++. If you need GC, use a GC enabled language - some of them claim to be very performant, ie D, OCaml...
IMHO, for the C++ community threading is much more important issue than GC.
|
|
|
> But these rules are often more restrictive, make writing > threaded code more complicated, and have a higher > potential for error than native methods. It's more of a > step backward than forward.
I suppose it depends on whether you want to be a C++ programmer or a <OS of choice> C++ programmer or (even worse) <OS> <processor> C++ programmer. Or how about just a single processor X86 Windows C++ programmer. It is much easier to develop for multiple targets if you have a common, albeit more restrictive, set of design rules.
Do you know how the different memory models supported by various versions of SPARC behave? I gather that some of these are rarely used because although allowing greater performance they break assumptions used by too many applications.
|
|