Chenyu ZhengCSCI 5828 – Spring 2010Prof. Kenneth M. AndersonUniversity of Colorado at Boulder Actuality Introduction Concurrency framework in the 2010 new C++ standard History of multi-threading in C++ Feature demonstration Comparison between previous concurrency solutions and current concurrency support Framework Component Analysis Thread Management Data Sharing Synchronization of Concurrent Operations The New C++ Memory Model Operations on Atomic Types 11 years after the original C++ Standard (published in 1998), the C++ Standards committee is giving the language and its supporting library a major overhaul. The C++0x is due to be published at the end of 2010 and will bring with it a whole swathe of changes that will make working with C++ easier and more productive. One of the most significant new features: the support of multi-threaded programs allow us to write multi-threaded C++ programs without relying on platform-specific extensions => write portable multi-threaded code with guaranteed behavior The 1998 C++ Standard Does not acknowledge the existence of threads The memory model is not formally defined=> Can't write multi-threaded applications without compiler-specific extensions Solutions compiler vendors add extensions to the language themselves C APIs led compiler vendors to support multi-threading with various platform specific extensions. POSIX C Standard Microsoft Windows API More Advanced Solutions Accumulate sets of C++ classes that wrap the underlying platform specific APIs to provide higher level facilities for multi-threading that simplify the tasks Application frameworks such as MFC General-purpose C++ libraries such as Boost and ACE Common design among these solutions the use of the Resource Acquisition Is Initialization (RAII) idiom with locks to ensure that mutexes are unlocked when the relevant scope is exited Lack of a formal multi-threading-aware memory model and standard library support means Development has to allow the use of the corresponding C API for the platform ensure the C++ runtime library works in the presence of multiple threads Optimization is limited when trying to gain higher performance by using knowledge of the processor hardware writing cross-platform code where the actual behavior of the compilers varies between platforms Although not perfect, we survived, WHY? a large number of multi-threaded C++ programs have been written and because of the development of the compilers and processor Concurrency Support in the New Standard Brand new thread-aware memory model Extended standard library support managing threads protecting shared data synchronizing operations between threads low-level atomic operations=> Provides both integrated high-level facilities and sufficient low-level facilities Abstraction Penalty Costs associated with using any high-level facilities compared to using the underlying low-level facilities directly Not Really Although sometimes the use of high-level facilities does comes with a performance cost due to the additional code that must be executed in general the cost is no higher than would be incurred by writing equivalent functionality by hand the compiler may well inline much of the additional code anyway And Also Design… Even if profiling does demonstrate that the bottleneck is in the C++ Standard Library facilities, it may be due to poor application design rather than a poor library implementation Before we go to the component analysis the functions and classes for managing threads are declared in <thread> Initial Function Every C++ program has at least one thread, which is started by the C++ runtime: initial function: main() std::thread object named t has the new function hello() as its initial function Thread Management Data Sharing Synchronization of Concurrent Operations The New C++ Memory Model Operations on Atomic Types Using function void-returning function that takes no parameters Using class Pass an instance of a class with a function call operator to the std::thread constructor Attention: scope and lifetime Since the callable object supplied to the constructor is copied into the thread, the original object can be destroyed immediately. However, if the object contains any pointers or references, it is important to ensure that those pointers and references remain valid as long as they may be accessed from the new thread join(): block and wait Inserting a call to std::thread instance.join() before the to ensure that the thread was finished before the closing brace of the function body would therefore be sufficient function was exited, and thus before the local variables were destroyed This code ensures that a thread with access to local state is finished before the function exits whether the function exits normally (#1) by an exception (#2) Standard Resource Acquisition Is Initialization idiom (RAII) joinable() tests to see if the std::thread object is joinable before calling join(). join() can only be called once for a given thread of execution it would therefore be a mistake to do so if the thread had already been joined with =delete The copy constructor and copy-assignment operator are marked ensure they are not automatically provided by the compiler copyed or assigned objects probably would outlive the scope of the thread it was joining detach() member function of the std::thread Destroy std::thread object at the point where you wish to detach the thread After the call completes the std::thread object is no longer associated with the actual thread of execution no longer joinable Passing additional arguments to the std::thread constructor BY Passing arguments to the callable object or function The arguments are copied into internal storage, where they can be accessed by the newly created thread of execution, even if the corresponding parameter in the function is expecting a reference. This code will invoke my_x.do_lengthy_work() on the new thread the third argument to the std::thread constructor will be the first argument to the member function, and so forth #1: a new thread is started and associated with t1 #2: ownership of some_function is transferred over to t2 when t2 is constructed, t1 no longer has
View Full Document