Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: [email protected]...

52
Computer Science Simple C++ (Vol.2) simpler generic & library code through better C++11 usage ACCU 2012, Oxford, UK slides: http://wiki.hsr.ch/PeterSommerlad/ Prof. Peter Sommerlad Director IFS Institute for Software Oxford, 26th of April 2012 Donnerstag, 26. April 12

Transcript of Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: [email protected]...

Page 1: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

Computer Science

Simple C++ (Vol.2)simpler generic & library code through better C++11 usage

ACCU 2012, Oxford, UK

slides: http://wiki.hsr.ch/PeterSommerlad/

Prof. Peter SommerladDirector IFS Institute for SoftwareOxford, 26th of April 2012

Donnerstag, 26. April 12

Page 2: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

Contact Info: Prof. Peter Sommerladphone: +41 55 222 4984

email: [email protected]

LinticatorLinticator gives you immediate feedback on programming style and common programmer mistakes by integrating Gimpel Software’s popular PC-lint and FlexeLint static analysis tools into Eclipse CDT.PC-lint and FlexeLint are powerful tools, but they are not very well integrated into a modern developer's workflow. Linticator brings the power of Lint to the Eclipse C/C++ Development Tools by fully integrating them into the IDE. With Linticator, you get continuous feedback on the code you are working on, allowing you to write better code.

• Automatic Lint ConfigurationLint's configuration, like include paths and symbols, is automatically updated from your Eclipse CDT settings, freeing you from keeping them in sync manually.

• Suppress Messages EasilyFalse positives or unwanted Lint messages can be suppressed directly from Eclipse, without having to learn Lint's inhibition syntax–either locally, per file or per symbol.

• Interactive “Linting” and Information DisplayLint is run after each build or on demand, and its findings are integrated into the editor by annotating the source view with interactive markers, by populating Eclipse’s problem view with Lint’s issues and by linking these issues with our Lint Documentation View.

• Quick-Fix Coding ProblemsLinticator provides automatic fixes for a growing number of Lint messages, e.g, making a reference-parameter const can be done with two keystrokes or a mouse-click.

Register at http://linticator.com if you want to try it for 30 days or order via email. Linticator is available for Eclipse CDT 3.4 (Ganymede), 3.5 (Helios) and later. It is compatible with Freescale CodeWarrior.

see more on http://linticator.com

Pricing for Linticator is CHF 500.- per user (non-floating license). A maintenance contract that is required for updates costs 20% of license fee per year. The compulsory first maintenance fee includes 6 month of free updates.Orders, enquiries for multiple, corporate or site licenses are welcome at [email protected].

Linticator requires a corresponding PC-Lint (Windows) or FlexeLint license per user.

IFS Institute for SoftwareIFS is an institute of HSR Rapperswil, member of FHO University of Applied Sciences Eastern Switzerland.

In January 2007 IFS became an associate member of the Eclipse Foundation.

The institute manages research and technology transfer projects of four professors and hosts about a dozen assistants and employees. http://ifs.hsr.ch/

IFS INSTITUTE FOR SOFTWARE! HSR Hochschule für Technik, Oberseestrasse 10, CH - 8640 Rapperswil! http://ifs.hsr.ch

Page 3: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

Contact Info: Prof. Peter Sommerladphone: +41 55 222 4984

email: [email protected]

Includator#include Structure Analysis and Optimization for C++ for Eclipse CDTThe Includator plug-in analyzes the dependencies of C++ source file structures generated by #include directives, suggests how the #include structure of a C++ project can be optimized and performs this optimization on behalf of the developer. The aim of these optimizations is to improve code readability and quality, reduce coupling and thus reduce duration of builds and development time of C++ software.

Includator Features• Find unused includes

Scans a single source file or a whole project for superfluous #include directives and proposes them to be removed. This also covers the removal of #include directives providing declarations that are (transitively) reachable through others.

• Directly include referenced filesIgnores transitively included declarations and proposes to #include used declarations directly, if they are not already included. This provides an “include-what-you-use” code structure.

• Organize includesSimilar to Eclipse Java Development Tool's Organize imports feature for Java. Adds missing #include directives and removes superfluous ones.

• Replace includes with forward declarationsLocates #include directives for definitions that can be omitted, when replacing them with corresponding forward declarations instead. This one is useful for minimizing #includes and reducing dependencies required in header files.

• Static code coverageMarks C++ source code as either used, implicitly used or unused by transitively following C++ elements’ definitions and usages. This helps to trim declarations and definitions not used from your source code. In contrast to dynamic code coverage, such as provided by our CUTE plug-in (http://cute-test.com) it allows to determine required and useless C++ declarations and definitions instead of executed oder not-executed statements.

• Find unused filesLocates single or even entangled header files that are never included in the project’s source files.

User Feedback and ParticipationIncludator is in beta testing. Register at http://includator.com if you are interested in a 30-day trial license or if you want to be notified about Includator’s release.

see more on http://includator.comto be released 2012

Individual licensing TBA. Free 30-day trial licenses available by registering at http://includator.com/account/register.

Enquiries for corporate or site licenses are welcome at [email protected].

IFS INSTITUTE FOR SOFTWARE! HSR Hochschule für Technik, Oberseestrasse 10, CH - 8640 Rapperswil! http://ifs.hsr.ch

#

Get Swiss Quality

Page 4: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

Contact Info: Prof. Peter Sommerlad+41 55 222 4984email: [email protected]

Green Bar for C++ with CUTEEclipse plug-in for C++ unit testing with CUTEAutomated unit testing improves program code quality, even under inevitable change and refactoring. As a side effect, unit tested code has a better structure. Java developers are used to this because of JUnit and its tight integration into IDEs like Eclipse. We provide the modern C++ Unit Testing Framework CUTE (C++ Unit Testing Easier) and a corresponding Eclipse plug-in. The free CUTE plug-in features:

• wizard creating test projects (including required framework sources)

• test function generator with automatic registration

• detection of unregistered tests with quick-fix for registration

• test navigator with green/red bar (see screen shots to the right)

• diff-viewer for failing tests (see screen shot down to the right)

• code coverage view with gcov (see screen shot below)

Support for TDD and Mock Objects (Mockator)The CUTE plug-in incorporates support for Test-Driven Development (TDD) in C++. It will support code generation for test doubles and mock objects in spring 2012:

• create unknown function, member function, variable, or type from its use in a test case as a quick-fix (see screen shots below)

• move function or type from test implementation to new header file. (More MOVE Refactorings are becoming available in spring 2012)

• toggle function definitions between header file and implementation file, for easier change of function signature, including member functions (now part of CDT itself)

• extract template parameter for dependency injection, aka instrumenting code under test with a test stub through a template argument (instead of Java-like super-class extraction)

• automatic generation of test stubs and mock classes from test cases (spring 2012)

• extract super-class for dependency injection (spring 2012)

IFS Institute for SoftwareIFS is an Institute of HSR Rapperswil, member of FHO University of Applied Sciences Eastern Switzerland.In January 2007 IFS became an associate member of the Eclipse Foundation. The institute manages research and technology transfer projects of four professors and hosts a dozen assistants and employees. http://ifs.hsr.ch/

Eclipse update site for installing the free CUTE plug-in: http://cute-test.com/updatesite

IFS INSTITUTE FOR SOFTWARE HSR Hochschule für Technik, Oberseestrasse 10, CH - 8640 Rapperswil! http://ifs.hsr.ch

Get Swiss Quality

Page 5: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

Contact Info: Prof. Peter Sommerlad+41 55 222 4984email: [email protected]

SConsolidatorEclipse CDT plug-in for SConsSCons (http://www.SCons.org/) is an open source software build tool which tries to fix the numerous weaknesses of make and its derivatives. For example, the missing automatic dependency extraction, make’s complex syntax to describe build properties and cross-platform issues when using shell commands and scripts. SCons is a self-contained tool which is independent of existing platform utilities. Because it is based on Python a SCons user has the full power of a programming language to deal with all build related issues.

However, maintaining a SCons-based C/C++ project with Eclipse CDT meant, that all the intelligence SCons puts into your project dependencies had to be re-entered into Eclipse CDT’s project settings, so that CDT’s indexer and parser would know your code’s compile settings and enable many of CDT’s features. In addition, SCons’ intelligence comes at the price of relatively long build startup times, when SCons (re-) analyzes the project dependencies which can become annoying when you just fix a simple syntax error.

SConsolidator addresses these issues and provides tool integration for SCons in Eclipse for a convenient C/C++ development experience. The free plug-in features:

• conversion of existing CDT managed build projects to SCons projects• import of existing SCons projects into Eclipse with wizard support• SCons projects can be managed either through CDT or SCons

• interactive mode to quickly build single source files speeding up round trip times• a special view for a convenient build target management of all workspace projects

• graph visualization of build dependencies with numerous layout algorithms and search and filter functionality that enables debugging SCons scripts.

• quick navigation from build errors to source code locations

More information:

http://SConsolidator.com/

Install the free SConsolidator plug-in from the following Eclipse update site:

http://SConsolidator.com/update

SConsolidator has been successfully used to import the following SCons-based projects into Eclipse CDT:

• MongoDB

• Blender

• FreeNOS

• Doom 3

• COAST (http://coast-project.org)

IFS INSTITUTE FOR SOFTWARE HSR Hochschule für Technik, Oberseestrasse 10, CH - 8640 Rapperswil! http://ifs.hsr.ch!

!

!

Page 6: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

2

Peter [email protected] Credo:

Work Areas

Refactoring Tools (C++, Scala, ...) for Eclipse

Decremental Development (make SW 10% its size!)

Modern Software Engineering

Pattern Books (co-author)

Pattern-oriented Software Architecture Vol. 1

Security Patterns

Background

Diplom-Informatiker / MSc CS (Univ. Frankfurt/M)

Siemens Corporate Research - Munich

itopia corporate information technology, Zurich

Professor for Software Engineering, HSR Rapperswil, Director Institute for Software

People create Software

communication

feedback

courage

Experience through Practice

programming is a trade

Patterns encapsulate practical experience

Pragmatic Programming

test-driven development

automated development

Simplicity: fight complexity

Donnerstag, 26. April 12

Page 7: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

A Quick Reality Check - please raise your hands

I prefer using STL algorithms over loops.

I am familiar with the Boost library collection.

I have provided some of the Boost libraries

I've memorized Andrej Alexandrescu's "Modern C++ Design"

I've read the new ISO C++11 standard

I wrote parts of the ISO C++ standard

I know most of the ISO C++ standard by heart (not me :-)

3

Donnerstag, 26. April 12

Page 8: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

Outline (Part 2)

Move Semantics - do I need to care?

overflow/some overlap part 1

Literal types and constexpr

User-defined Literals

Simple (variadic) templates

recursion

sizeof...

static_assert

local classes as template parameters

Demo Mockator: usage

Regular Expressions

not yet ready in g++ 4.7.0 lib

Simpler generics

auto and return types

decltype

type traits

Simple concurrency: async

4

Donnerstag, 26. April 12

Page 9: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

Move Semantics - Do I need to care? -> Usually not!

In non-library code you might not need to care at all, things just work!

often you do not need to care! Only (library) experts need to.

for elementary (aka trivial) types move == copy anyway

R-Value-References allow optimal "stealing" of underlying object content

copy-elision by compilers does this today for many cases already

e.g., returning std::string or std::vector

Type&& denotes an r-value-reference: reference to a temporary object

std::move(var) denotes passing var as rvalue-ref and after that var is "empty"

if used as argument selects rvalue-ref overload, otherwise using var would select lvalue-ref overload or const-ref overload

like with const &, rvalue-ref && bound to a temporary extends its lifetime

R-value references are also serving a second purpose: perfect forwarding

see std::forward() - that actually does nothing, except avoiding unnecessary copies and provides the correct overloads of a called function, based on your callers arguments

only needed in library/generic code dealing with passing arguments through

5

Donnerstag, 26. April 12

Page 10: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

New Value Terminology in the Standard - rvalue-References

lvalue - "left-hand side of assignment" - can be assigned to

glvalue - "general lvalue" - something that can be changed

rvalue - "right-hand side of assignment" - can be copied

prvalue - "pure rvalue" - return value, literal

xvalue - "eXpiring value - object at end of its lifetime" - can be pilfered - moved from

rvalue-references refer to temporaries or pilfer-able variables

6

c� ISO/IEC N3290

4 There is a partial ordering on cv-qualifiers, so that a type can be said to be more cv-qualified than another.Table 9 shows the relations that constitute this ordering.

Table 9 — Relations on const and volatileno cv-qualifier < constno cv-qualifier < volatileno cv-qualifier < const volatile

const < const volatilevolatile < const volatile

5 In this International Standard, the notation cv (or cv1, cv2, etc.), used in the description of types, representsan arbitrary set of cv-qualifiers, i.e., one of {const}, {volatile}, {const, volatile}, or the empty set.Cv-qualifiers applied to an array type attach to the underlying element type, so the notation “cv T,” whereT is an array type, refers to an array whose elements are so-qualified. Such array types can be said to bemore (or less) cv-qualified than other types based on the cv-qualification of the underlying element types.

3.10 Lvalues and rvalues [basic.lval]1 Expressions are categorized according to the taxonomy in Figure 1.

����������

�� � ��� �

�� � ��� � ���� �

Figure 1 — Expression category taxonomy

— An lvalue (so called, historically, because lvalues could appear on the left-hand side of an assignmentexpression) designates a function or an object. [ Example: If E is an expression of pointer type, then*E is an lvalue expression referring to the object or function to which E points. As another example,the result of calling a function whose return type is an lvalue reference is an lvalue. — end example ]

— An xvalue (an “eXpiring” value) also refers to an object, usually near the end of its lifetime (so that itsresources may be moved, for example). An xvalue is the result of certain kinds of expressions involvingrvalue references (8.3.2). [ Example: The result of calling a function whose return type is an rvaluereference is an xvalue. — end example ]

— A glvalue (“generalized” lvalue) is an lvalue or an xvalue.— An rvalue (so called, historically, because rvalues could appear on the right-hand side of an assignment

expression) is an xvalue, a temporary object (12.2) or subobject thereof, or a value that is not associatedwith an object.

— A prvalue (“pure” rvalue) is an rvalue that is not an xvalue. [ Example: The result of calling a functionwhose return type is not a reference is a prvalue. The value of a literal such as 12, 7.3e5, or true isalso a prvalue. — end example ]

Every expression belongs to exactly one of the fundamental classifications in this taxonomy: lvalue, xvalue,or prvalue. This property of an expression is called its value category. [ Note: The discussion of each built-in

§ 3.10 78

Type & Type && TypeType const &

Donnerstag, 26. April 12

Page 11: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

Move Semantic

Goal: no unnecessary object copies, transfer temporaries efficiently

Mechanisms:

r-value references: Type&&

move-ctors Type(Type&&), move-assignment operator=(Type&&)

deleted copy-ctor, copy assignment -> move-only type

std::move(lvalue) -> prepare lvalue(aka variable) to move from

relevant for classes that manage (expensive) internals and can hand those over

e.g. containers

relevant for classes that couldn't keep invariant if copied

e.g. std::unique_ptr, std::future, "single-ownership" objects

7

Donnerstag, 26. April 12

Page 12: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

Copy Elision works even before C++11

"normal" users can rely on good compiler technology

return by value is OK (even with C++03)

aka "return value optimization"

With moveable types, pass by value can be more efficient than pass by const&

subtle things happen, with pass by value a temporary gets moved into parameter

moving from a const& when a copy of the parameter is needed, doesn't work

If you do not explicitly design your own move-only/move-enabled types you usually do not need to care when using the standard library

8

Donnerstag, 26. April 12

Page 13: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

Example of Move Semantic with Move-only Type9

#include <iostream>struct MoveOnly{ MoveOnly() = default; MoveOnly(MoveOnly&&) { std::cout << "Move constructor called\n"; } MoveOnly(const MoveOnly&) = delete; // implicitly};void f(MoveOnly) { std::cout << "f(MoveOnly) called\n"; }void g(MoveOnly&&) { std::cout << "g(MoveOnly&&) called\n"; }void g(MoveOnly const &){ std::cout << "g(MoveOnly const&) called\n"; }int main(){ f( MoveOnly{} ); // rvalue temporary g( MoveOnly{} ); // rvalue temporary std::cout << "moving lvalues:\n"; MoveOnly mv{}; // lvalue //f(mv); // doesn't compile, lvalue cannot be passed f(std::move(mv)); // make an rvalue from lvalue g(mv); // binds to const-ref g(std::move(mv)); // binds to rvalue-ref}

Move constructor calledf(MoveOnly) calledg(MoveOnly&&) calledmoving lvalues:Move constructor calledf(MoveOnly) calledg(MoveOnly const&) calledg(MoveOnly&&) called

move ctor calls might be elided!as here:

f(MoveOnly) calledg(MoveOnly&&) calledmoving lvalues:Move constructor calledf(MoveOnly) calledg(MoveOnly const&) calledg(MoveOnly&&) called

Donnerstag, 26. April 12

Page 14: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

Move-enabling a class: DO NOT DO THAT YOURSELF!

If you implement a class that does its own resource management of large resources you might want to do your own copy and move implementation

first: resist! DON'T DO THAT! if you do not have performance issues with too many copies, everything is fine.

second: let standard library classes do the resource management for you

then, compiler generated member-wise copy and member-wise move is fine and fast!

never ever use malloc or new in your code again (new is only allowed to initialize a unique_ptr)

third: if you can prove your class gets copied too often you might try a simple version

only if that fails, learn all details about move-semantics and try yourself,

but be warned, it is very easy to get it wrong!

fourth: become a moveable-type expert first, before you roll your own!

I experimented, enabling move constructor and assignment can make things slower

(1.5 .. 3 times in my very simple examples)

10

Donnerstag, 26. April 12

Page 15: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

What to use to profit from move semantics?

If you pass an object x to a function foo that has an r-value-reference overload use std::move(x) as argument

that makes it an rvalue deliberately, you promise not to rely on x's content afterwards

11

struct X{};

//void foo(X v){ // ambiguous//std::cout << "foo(X) \n";//}void foo(X& lv){ // ref std::cout << "foo(X&) \n";}void foo(X&& rvr){ // rvalue ref std::cout << "foo(X&&) \n";}void foo(X const& rv){ // const ref std::cout << "foo(X const&) \n";}void foo(X const && rvr){//rvconst ref std::cout << "foo(X const &&) \n";}

int main(){ X x{}; // value X const &y=X{}; // const ref X &z=x; // reference X const a{}; // constant X &&b=X{}; // rvalue ref X const &&c=X{}; // const rv-ref

foo(x); foo(const_cast<X const&>(x)); foo(std::move(x)); foo(y); foo(std::move(y)); foo(z); foo(std::move(z)); foo(a); foo(std::move(a)); foo(b); foo(std::move(b)); foo(c); foo(std::move(c));}

foo(X&) foo(X const&) foo(X&&) foo(X const&) foo(X const &&) foo(X&) foo(X&&) foo(X const&) foo(X const &&) foo(X&) foo(X&&) foo(X const&) foo(X const &&)

output:

rvalue const ref (X const &&) is not very useful in practice!

Donnerstag, 26. April 12

Page 16: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

Defining classes!12

about 7 pages of rules for compiler provided copy/move ctor and destructor in the standard document.

It is very hard to know and apply them all correctly.

However, C++11 allows to use appropriate library stuff so that you do not need to care!

containers, strings, smart pointers

Write your classes in a way that you do not need to care

let the standard library provide all resource management for you!

std::string, std::vector and the other containers are your friends

use std::shared_ptr<X> if you intend to keep your class copyable and share the resource

keeps your class default copyable and moveable

use std::unique_ptr<Y> if you want to be the only one caring for your resources

this makes your class move-only, if you do not inhibit move-ctor/move-assignment otherwise

No more manual memory management needed, if done right

even better than in Java, because destruction is deterministic!

Donnerstag, 26. April 12

Page 17: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

Literal Types - what for?

C++ wants to allow user-defined class types behave similarly and with equal efficiency than built-in types

so far syntactical equivalence was given, but you couldn't define a type with a constructor that would be evaluated at compile time, e.g., to initialize static data (pre C++11)

Literal types in C++11 allow to define types which can be guaranteed initialized or computed with at compile time.

Now it is possible to create your own class-based types that work like int!

e.g., std::complex<double> is now a literal type, compile time constants possible!

Key mechanism: constexpr

constexpr constructors

trivial destructor (one that is provided by the compiler)

only members of literal type

everything that would require run-time memory allocation, e.g., std::string is not allowed!

but a bit more than with just trivial types

13

Donnerstag, 26. April 12

Page 18: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

constexpr functions

if called with constants must be able to evaluate a constant at compile time

all parameters and return type must be literal types (relaxed for templates)

just a single return statement (but can use recursion!)

14

constexpr int squarei(int i){ using namespace std; // allowed return i * i;}

int main(){ constexpr int i{42}; // compile time constant const int j{i}; // could be initialized at run time constexpr int k{squarei(j)}; char s[squarei(j)]; std::cout << " i = "<< i << " j = " << j << " k = "<< k << "\n";

std::cout << "sizeof s = "<< sizeof(s)<< "\n"; int l{squarei(2)};//constexpr int m{squarei(l)}; // not allowed const int n{squarei(l)}; // allowed initialized at run-time std::cout << "square(l) = "<< squarei(l) << " n = " << n << "\n";

i = 42 j = 42 k = 1764sizeof s = 1764square(l) = 16 n = 16

output:

Donnerstag, 26. April 12

Page 19: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

constexpr function example: compile-time fibonacci

You can use recursion and conditional evaluation:

but do not stress your compiler too much!

15

constexpr unsigned long long fib(unsigned long long i){ return (i>2)?fib(i-1)+fib(i-2) :(i>0?1:0);}

int main(){ constexpr auto f=fib(42); std::cout << "fib(42) = " << f <<"\n"; constexpr auto g=fib(5); std::cout << "fib(5) = " << g <<"\n";}

fib(42) = 267914296fib(5) = 5

output:

Donnerstag, 26. April 12

Page 20: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

trivial and literal types

user-defined trivial types == C-struct (more or less)

Literal types allow for guaranteed compile-time initialization

but have restrictions on what you can actually do at compile time

but you get encapsulation plus compile time initialization!

16

struct trivial { int x,y;};constexpr trivial y{1,2};

struct non_trivial{ non_trivial(int x,int y) :x{x},y{y}{}private: int x,y;};// doesn't compile//constexpr non_trivial x{4,2};static const non_trivial v{3,1};// initialized (may be) at run time

struct Coord { constexpr Coord(int x, int y):x{x},y{y}{} constexpr int getx()const{return x;} constexpr int gety()const{return y;} constexpr Coord mirrorx()const{return Coord{x,-y};} //constexpr Coord transpose(){ // return (std::swap(x,y), *this); // } // swap is not constexpr Coord transpose(){ return (std::swap(x,y), *this);}private: // not allowed in trivial types int x,y;};constexpr Coord p{1,2};constexpr int i{p.getx()};

A literal type:

Donnerstag, 26. April 12

Page 21: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

UDL User-Defined Literals - why?

Literals without dimension can be confusing in some domains

miles vs. kilometers

speed in mph, km/h, mach or c units

String literals in C++ aren't std::strings

problem with

auto s="hello";

It would be nice to spell out complex numbers like

auto c=2_r+1_i; auto d=1_il+1.0l;

Or even to have binary literals in program code

(for the younger ones who no longer can read octal :-)

17

Donnerstag, 26. April 12

Page 22: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

UDL example: literals for lengths18

namespace lengths_in_meter {// norm everything to metersconstexprlong double operator"" _feet(long double d){ return d*0.3048;}constexprlong double operator"" _feet(unsigned long long d){ return d*1.0_feet;}constexprlong double operator"" _yard(long double d){ return d*3_feet;}// and so on...} // lengths_in_meter

void testYardsAndFeet(){ using namespace lengths_in_meter; ASSERT_EQUAL_DELTA(0.9144_m,1_yard,0.00001); ASSERT_EQUAL_DELTA(0.9144_m,1e0_yard,0.00001); ASSERT_EQUAL(1_yard,3_feet);}void testKmAndMiles(){ using namespace lengths_in_meter; ASSERT_EQUAL(1000.0_m,1_km); ASSERT_EQUAL_DELTA(1609.344_m,1_mi,0.0001); ASSERT_EQUAL(100.0_m,0.1_km);}

Donnerstag, 26. April 12

Page 23: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

Specifying dimensions with UDL operator""

Put your own UDL operators in a namespace

lookup is always unqualified, but you want to use short names that might easily conflict

this is a situation where a local using namespace is allowed

if mixing dimensions choose one common dimension, e.g., meters for lengths

may be even put that meta information into the namespace's name

If defining UDL operator"" for numeric values, you often want to overload both versions taking numbers and make it constexpr

operator"" _km(long double)

operator"" _km(unsigned long long)

but then return the same type, unless you want to do something specific for integral values

UDL names must start with an underscore '_'

and when defining operator"" you need a space between "" and _udl

19

Donnerstag, 26. April 12

Page 24: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

Problem: auto with "string literals"

What is the type of s?

auto s="hello";

my solution:

yes, it is a std::string!

but wait, why not overload?

well, that one is only for numbers:

20

// cannot be constexpr, string not literal typestd::string operator"" _str(char const *s,size_t l){ return std::string(s,l);}

void testStringLiteral(){ auto s="hallo"_str; ASSERT_EQUAL("hallo",s); ASSERT_EQUAL(5,s.length());}

std::string operator"" _str(char const *s){ return std::string(s);} void testQuoteLessStringLiteral(){

auto s=123_str; ASSERT_EQUAL("123",s); //auto t=hallo_str; // doesn't work=identifier auto u=1.234_str; ASSERT_EQUAL("1.234",u);}

Donnerstag, 26. April 12

Page 25: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

auto with complex numbers without std::complex<long double>...

Wouldn't it be nice to be able to write:

Well, that is possible:

21

auto d = 1_il + 1.0l; // std::complex<long double>{1.0,1.0} auto c = 1_i + 1_r; // std::complex<double>{1,1} c -= 1_i; ASSERT_EQUAL(1.0,c.real()); ASSERT_EQUAL(0.0,c.imag()); ASSERT_EQUAL(1.0l,d.imag());

namespace mycomplex{constexprstd::complex<long double> operator"" _il(long double d){ return std::complex<long double>{0,d};}constexprstd::complex<long double> operator"" _il(unsigned long long d){ return std::complex<long double>{0,static_cast<long double>(d)};}constexprstd::complex<long double> operator"" _rl(long double d){ return std::complex<long double>{d,0};}// and so on...} // mycomplex

Donnerstag, 26. April 12

Page 26: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

What about binary literals...

Wouldn't it be nice to write something like:

a solution (partly inspired by Paul Preney, see here)

use a UDL operator that is a variadic template taking char...

the compiler will use anything in front of "_bits" as the template argument

to actually calculation we need to recurse with an type template bitsImpl<> at compile time

22

void testBinaryLiterals() { char a[100_bits]; // 4 elements - compile time computed! ASSERT_EQUAL(4,sizeof(a)); ASSERT_EQUAL(32ull,100000_bits);//1234_bits; // will trigger static_assert}

template <char... Digits>constexpr unsigned long long operator"" _bits(){ return bitsImpl<Digits...>::value;}

Donnerstag, 26. April 12

Page 27: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

calculating the value of binary literals at compile time

we start out with a forward declaration:

when there is a '0' in the front, nothing to do, cut it and ask for the remaining value:

when there is a '1' shift it left by the length of the remaining Digits... and or it with the value of the remaining digits:

we just need the generic one as a base case for recursion and check if there are any wrong digits left over to generate a nicer compile time error instead of silence

23

template <char... Digits>struct bitsImpl<'1',Digits...>{ static constexpr unsigned long long value= bitsImpl<Digits...>::value|(1ULL<<sizeof...(Digits));};

template <char... Digits>struct bitsImpl;

template <char... Digits>struct bitsImpl<'0',Digits...>{ static constexpr unsigned long long value=bitsImpl<Digits...>::value;};

// serves also as base case of recursiontemplate <char... Digits>struct bitsImpl{ static_assert(! sizeof...(Digits),"_bits must be 0 or 1"); static constexpr unsigned long long value=0;};

Donnerstag, 26. April 12

Page 28: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

What the hell is template <char... Digits> and Digits...?

Welcome to variadic templates!

consider it .../varargs, but for templates at compile time

great relief for template-meta-programming (who's doing that)

have a look at boost::bind()'s implementation to see what horror you get with variable number of arguments in template functions -> you need to specify all overloads manually or use preprocessor meta-programming to get that.

Problem: where to place ...?

at template parameter definition after typename or non-type paramter's type

template <typename...TYPES>

TYPES is now a "parameter pack"

at parameter pack usage (aka pack expansion) after the parameter pack's name

return std::tuple<TYPES...>{};

after sizeof... to obtain the number of elements in the parameter pack

sizeof...(Digits)

To actually do something useful it requires often recursive template specializations

do not forget the base case!

24

Donnerstag, 26. April 12

Page 29: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

A type-safe print(std::ostream&, ...)

printf(...) is horribly unsafe,

but out<<a<<b<<c<<d<<f; looks ugly! here is a potential solution:

25

// base case overloadvoid print(std::ostream &out) { out << "\n";}//variadic templatetemplate<typename Head, typename... Tail>void print(std::ostream &out, Head const& head, Tail const& ...tail) { out << head; if (sizeof...(tail)) { out << ", "; } print(out,tail...); //recurse on tail}void testVariadicPrint(){ std::ostringstream out{}; print(out,1,2,3,"hello",' ',"world"); ASSERT_EQUAL("1, 2, 3, hello, , world\n",out.str());}

cut-off head

Donnerstag, 26. April 12

Page 30: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

What is static_assert(b,msg)?

it is a compile-time assert

allows for nicer compile errors and for checking your code's assumptions about its environment

message is not optional and must be a string literal! (already an issue for the next std)

compilation fails if constexpr condition is false

useful for compile time checks, such as sizeof(unsigned)==4

especially useful with type traits that allow querying type information at compile time

26

// serves also as base case of recursiontemplate <char... Digits>struct bitsImpl{

static_assert(! sizeof...(Digits),"_bits must be 0 or 1"); static constexpr unsigned long long value=0;};

static_assert(sizeof(int) == 8,"int is not 64 bit");

static_assert(std::is_unsigned<char>::value,"char is signed");

Donnerstag, 26. April 12

Page 31: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

Local Classes as Template Arguments

That is now allowed. Template arguments no longer restricted to namespace-level types.

However, some restrictions still apply, e.g., they cannot have member templates!

Usage scenario: Test-Stub and Mock-Object Generation with Mockator

Little Demo

27

void testLoosingGame() { struct LoosingDie { int roll() const { return 1; } }; GameFourWinsT<LoosingDie> game; std::ostringstream out; game.play(out); ASSERT_EQUAL("You lost!\n",out.str());}

Donnerstag, 26. April 12

Page 32: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

TDD with CDT

TDD Refactoring

Unit Testing

Test-DrivenDevelopment

C++ CUTEwith Eclipse CDTin

and

CUTE http://cute-test.com - free!!!

simple to use - test is a function

understandable also for C programmers

designed to be used with IDE support

can be used without, but a slightly higher effort

deliberate minimization of #define macro usage

macros make life harder for C/C++ IDEs and forprogrammers

Donnerstag, 26. April 12

Page 33: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

Seams and Mocks

MockatorRefactoring Unit Testing

Seam Introduction

C++

Object SeamCompile Seam

Preprocessor SeamLink Seam

Legacy Code enabling

Test Double generation

Mock Object generation

Master Thesis by Michael Rüegginspired and supervised by Prof. Peter Sommerladalpha statushttp://sinv–56033.edu.hsr.ch/mockator/repo

Function Tracer generation

Donnerstag, 26. April 12

Page 34: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

Mockator Demo - Compile Seam using Templates

Extract Template Parameter

part of CUTE plug-in

Use Template in Test

introduce Mock object for DIE

create test double class...

add missing member function

implement test double code

Add Mock Object Support

check for expected calls (C++11)

additional features

dependency injection through

templates

abstract interface classes

30

Donnerstag, 26. April 12

Page 35: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

Mockator - Preprocessor Seam

mockator_malloc.h

mockator_malloc.c

Generating trace functions like this one is easy: Ctrl+Alt+T (on Linux)

Mockator passes mockator_malloc.h to the GNU compiler by using its -include option

31

#ifndef MOCKATOR_MALLOC_H_#define MOCKATOR_MALLOC_H_#include <cstdlib >int mockator_malloc(size_t size, const char *fileName, int lineNumber); #define malloc(size_t size) mockator_malloc((size),__FILE__,__LINE__)#endif

#include "mockator_malloc.h"#undef mallocint mockator_malloc(size_t size, const char * fileName, int lineNumber){//TODO your tracing code here return malloc(size);}

Donnerstag, 26. April 12

Page 36: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

Mockator - Link Seam - Shadowing & Wrapping Library Functions

Shadowing on Linux only using GCC Linker

Allows wrapping of functions in shared libraries

Both Linux and MacOS X supported

Mockator does all the hard work like

creating a shared library project,

adding dependencies to the dl library,

creating run-time configurations with the following env values, etc.,

Linux: LD PRELOAD=libName.so MacOS X:

DYLD FORCE FLAT NAMESPACE=1

DYLD INSERT LIBRARIES=libName.dylib

32

int foo(int i) { static void *gptr = nullptr; if(!gptr)gptr= dlsym(RTLD_NEXT,"_Z3fooi");typedef int (*fptr)(int); fptrmy_fptr= reinterpret_cast<fptr>(gptr); // TODO putyourcodehere return my_fptr(i);

}

Donnerstag, 26. April 12

Page 37: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

Regular Expressions (almost there, not yet in library of g++4.7.0

Demo: A simple grep implementation (requires clang++ and libstdc++):

33

#include <regex>#include <iostream>#include <sstream>// currently only works with clang++ and libstdc+++ not with g++ 4.7int main(int argc,char const *const *argv)try{ std::regex re(argv[1]); // doesn't work with g++4.7 yet std::string line; while(getline(std::cin,line)){ if (std::regex_search(line,re)) std::cout<<line<<std::endl; }}catch(std::exception &e){ std::cout << "caught exception..." << e.what() << " regex:"<<argv[1];}

Donnerstag, 26. April 12

Page 38: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

Simpler Generic Functions

Some simple generic functions have been hard to specify, e.g. square() when user-defined types might be used that overload operators in an interesting way.

trailing return type helps a bit, if function return type depends on arguments

For example, what if T defines operator*(T,T) returning something else than T?

Simpler Type Traits and Meta Functions

meta-function results are automatically considered types without ::type extractor

34

template <typename T>T square(T t){return t*t;}

Donnerstag, 26. April 12

Page 39: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

Problem: generic functions with multiple parameters

The following is a compile error, even though 5*0.5 is a valid expression

We can "fix" that with specifying providing two template parameters:

35

template <typename T>T mul(T t, T s){ return t*s;}

int main(){ auto j=mul(5,0.5); // compile error! std::cout << "j =" << j << "\n";}

template <typename T, typename U>T mul(T t, U u){ return t*u;}

int main(){ auto j=mul(5,0.5); std::cout << "j =" << j << "\n"; // what is the result?}

Donnerstag, 26. April 12

Page 40: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

using trailing return type specification with decltype

A better fix lets the compiler figure out the return type

unfortunately that requires a bit of code duplication

syntax inspired by lambdas, where it is often not needed, because it is deduced

could even be constexpr

36

template <typename T, typename U>auto mul(T t, U u)->decltype(t*u){ return t*u;}

int main(){ auto j=mul(5,0.5); std::cout << "j =" << j << "\n"; // what is the result?}

Donnerstag, 26. April 12

Page 41: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

Type queries and converters

Most of it previously defined by boost::type_traits already

some new stuff possible through compiler magic with C++11

A whole lot of type queries (too many to list)

very useful with typename template arguments

can be used with enable_if SFINAE tricks to select function template instantiations

Too much to discuss all

more to come...

a crazy example:

see also cute_equals.hfor more sane usages

37

#include <type_traits>#include <iostream>template <typename T>auto foo(T t)->typename std::make_unsigned<T>{ return std::make_unsigned<T>{};}template <typename META, typename T>auto bar(META m,T t)-> typename META::type{ return static_cast<typename META::type>(t);}int main(){ int const n=-5; auto m=foo(n); auto x=bar(m,n); std::cout << x << std::endl;}

Donnerstag, 26. April 12

Page 42: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

Simpler Concurrency

async and futures

thread

mutex, lock_guard and unique_lock

condition_variable

atomic<T>

thread_local storage class specifier

not all is yet implemented everywhere

some last-minute adjustments to the standard kept library implementors from adjusting

boost::thread allows to use many of the new standard (lower-level) features already on several platforms

38

Donnerstag, 26. April 12

Page 43: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

Simpler Concurrency

C++11 finally has a memory model that takes multi-threading and hardware parallelism into account

in addition to a language extension for thread-local variables and library support for low-level threading (thread, mutex, condition_variable) it provides an easy to use mechanism for asynchronous/parallel execution of a function

auto future_value=std::async(function, parameters);

function is started in parallel and future_value.get() obtains its result.

one can use it even within a single threaded environment

call is deferred until get() is called (std::launch::deferred as first parameter to async)

to force concurrent execution use std::launch::async as first parameter to async

Lambdas are a convenient way for applying std::async()

caution when capture is by reference, use copy-capture always instead

39

Donnerstag, 26. April 12

Page 44: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

A very simple example using async()40

#include <future>#include <iostream>#include <cmath>

double do_some_expensive_calculation(double input){! return std::sqrt(input); // simulate that}

int main(){! auto result=std::async(std::launch::async, do_some_expensive_calculation,81.0);! std::cout << "do some other useful things" << std::endl;! std::cout << "waiting for he result..." << std::endl;! std::cout << "the result is= "<< result.get()<< std::endl;}

Donnerstag, 26. April 12

Page 45: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

An async example

not very useful, but to show mechanism

41

#include <future> // defines async and future#include <iostream>#include <chrono>unsigned long long fibo_def(unsigned long long n){ if (n < 1) return 0; if (n < 2) return 1; auto f1 = std::async(fibo_def,n-1); // obtain future, eventually start thread auto f2 = std::async(fibo_def,n-2); // obtain future, eventually start thread return f1.get() + f2.get(); // use future's result}int main(int argc, char **argv){ if (argc < 2 || atoi(argv[1]) <1) { std::cout<< "Usage: "<< argv[0] << " number\n"; exit(1); } unsigned long long n=std::strtoull(argv[1],nullptr,10); using Clock=std::chrono::high_resolution_clock; using msec=std::chrono::milliseconds; Clock::time_point t0 = Clock::now(); // standard millisecond timing auto fibn=fibo_def(n); Clock::time_point t1 = Clock::now(); msec ms = std::chrono::duration_cast<msec>(t1 - t0); std::cout <<"fibo_def("<<n<<") = " << fibn<<" :" << ms.count() << "ms\n";}

Donnerstag, 26. April 12

Page 46: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

Simpler Concurrency - a note on futures

result of async is a std::future<result_type>

this cannot be copied, only moved, so no sharing is possible

allows for move-only result types

If the result needs to be used in several places and is copyable one can obtain a shared_future from async instead:

auto a_shared_future=std::async(function, parameters).share();you can call get() on a shared_future object multiple times and they will wait for the

result to become available.

42

Donnerstag, 26. April 12

Page 47: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

Simpler Low-level Concurrency - threads

First Rule: DO NOT USE THREADS and other low-level facilities!

you will get it wrong!

Many use POSIX-threads as C-library facilities in C++ code - DON'T! (even in C++03)

e.g., lock-unlock pairs are error-prone -> use RAII instead

C++11 provides std::lock_guard for that

std::thread provides thread abstraction

constructor and join() for forking and waiting-on other threads

std::thread t([]{ std::cout << " running parallel ";}); std::cout <<"main thread"; t.join();

before thread is destructed join() must be called on it (or detach()).

you can synchronize with mutexes and locks

43

Donnerstag, 26. April 12

Page 48: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

Simpler Low-Level Concurrency - lock_guard, unique_lock, call_once

Implement the Scoped-Locking idiom with std::lock_guard<mutex_type>

{ std::lock_guard<std::mutex> guard(theMutex); /* exclusive region */ ; }

For non-scoped locking consider using std::unique_lock<mutex_type>

made possible through "move-semantics", like unique_ptr for a lock

can be passed-to/returned-from functions to transfer ownership of lock

releases lock on destruction, if owned

only consideration is lifetime of wrapped mutex object must exceed uniqe_lock's lifetime

call_once() ensures that a function is only called by one out of many threads

static std::once_flag once; std::call_once(once, function, parameters);

once_flag is an opaque type, call_once works per once_flag instance.

convenient for lacy initialization/verification mechanisms that might be expensive

44

Donnerstag, 26. April 12

Page 49: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

Synchronization - Notification with std::condition_variable

std::condition_variable provides wait() for std::unique_lock<std::mutex>

thread must hold the lock when calling wait()

also variations including timing: wait_until() and wait_for()

all wait functions allow passing a predicate (bool function) as a condition

no external loop needed, wait returns when predicate becomes true or a timeout happens

notify_one() and notify_all() wake up threads blocked in wait()

spurious wakeups in wait() are allowed (need to check underlying predicate!)

45

Donnerstag, 26. April 12

Page 50: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

Low-low-level concurrency support: atomic<T>

C++11 atomics are designed to work together with C11 atomics

std::atomic<T> is a class template, however, interoperability with C11's atomics given

bool, integer types and pointers must be defined template specializations, others usually don't work

free functions and corresponding C-types allow intermixing C and C++ with same atomic variables

initialization of an atomic variable is non-atomic

all other defined operations are atomic

implementations can provide lock-free (aka fast) atomic implementations

only std::atomic_flag must be lock-free (a special version of std::atomic<bool>)

memory-order can be specified to further optimize code using atomics

46

Donnerstag, 26. April 12

Page 51: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

Thread Support on the Language Level: thread_local

a new "storage class" keyword can ensure that each thread gets its own version of a (global) variable. (thread_local static and thread_local extern make sense)

thread_local doesn't make sense for parameters or local variables allocated on the stack

thread_local variables live for the lifetime of a thread and are destructed, before it can be join()-ed. << need to check that, standard unclear wrt "thread exits"

thread_local variables have C++'s deterministic life-time guarantee. This raised heavy discussion on how to implement thread pools, where threads are recycled: should logically the thread_locals be deleted and re-created each time a thread from the pool is used? --> this is not resolved and if you use a thread pool, you cannot assume that when you hand a function to a thread in the pool to execute that the thread_local variables have an initial value.

thread_local on a local variable within a block implies static

thread_local can only applied to class members that are static member variables

47

Donnerstag, 26. April 12

Page 52: Simple C++ (Vol.2)Contact Info: Prof. Peter Sommerlad phone: +41 55 222 4984email: ifs@hsr.ch Includator #include Structure Analysis and Optimization for C++ for Eclipse CDT The Includator

© Peter Sommerlad

Questions ?

http://cute-test.com (Mockator will be here 3.Q2012)

http://linticator.com http://includator.com

http://sconsolidator.com (M. Rüegg as well)

[email protected] http://ifs.hsr.ch

48

Have Fun with C++ TDD, Mockator and

Refactoring!

Donnerstag, 26. April 12