Systems Programming & Beyond using C++ and D C++ Andrei - - PowerPoint PPT Presentation

systems programming beyond using c and d c
SMART_READER_LITE
LIVE PREVIEW

Systems Programming & Beyond using C++ and D C++ Andrei - - PowerPoint PPT Presentation

Systems Programming & Beyond using C++ and D C++ Andrei Alexandrescu andrei@erdani.com Prepared for LASER Summer School 2012 1 / 59 2012 Andrei Alexandrescu. c Prolegomena Assumption: You are intelligent and talented


slide-1
SLIDE 1

c

2012– Andrei Alexandrescu.

1 / 59

Systems Programming & Beyond using C++ and D C++

Andrei Alexandrescu

andrei@erdani.com

Prepared for LASER Summer School 2012

slide-2
SLIDE 2
slide-3
SLIDE 3

Prolegomena

c

2012– Andrei Alexandrescu.

3 / 59

  • Assumption: You are intelligent and talented
  • Won’t teach trivialities
  • Dwell on “diffs”
  • Focus on internalizing simple fundamentals with broad

impact instead of rote memorization

  • Only few errors are unforced in PL design
slide-4
SLIDE 4

Rules of Engagement

c

2012– Andrei Alexandrescu.

4 / 59

  • I ask question:
  • You raise hand
  • I acknowledge
  • You SHOUT
  • You ask question:
  • You raise hand
  • I ignore, microphone runners acknowledge
  • You raise hand with microphone in it
  • I acknowledge
  • You talk
  • No two consecutive questions
slide-5
SLIDE 5

Why?

c

2012– Andrei Alexandrescu.

5 / 59

slide-6
SLIDE 6

c

2012– Andrei Alexandrescu.

6 / 59

“OK, efficiency is the word. But then why wouldn’t I just use C or C + glue?”

slide-7
SLIDE 7

C

c

2012– Andrei Alexandrescu.

7 / 59

  • + Fast
  • + Close to the machine
  • − Weak abstraction mechanism
  • − No safety
  • − Verbose
slide-8
SLIDE 8

C + glue

c

2012– Andrei Alexandrescu.

8 / 59

  • + Flexibility
  • + Separation of concerns
  • + Get to use another language
  • − Hybrid object model and memory layout
  • − Impedance mismatch
  • − Get to use another language
slide-9
SLIDE 9

C++

c

2012– Andrei Alexandrescu.

9 / 59

  • + Perfect integration
  • + Better abstraction mechanisms than C
  • + Expressiveness, range
  • − Lack of flexibility
  • − Size
  • − Imperfections (e.g. safety)
slide-10
SLIDE 10

C++’s Computational Model

c

2012– Andrei Alexandrescu.

10 / 59

slide-11
SLIDE 11

C++

c

2012– Andrei Alexandrescu.

11 / 59

  • Part of many battles, most of which it won
  • Retrofitted with armor and weaponry, sent back to

battle

  • Amazing combination of old technology and new

human ingenuity

  • Aimed niche: efficiency AND modeling power
  • All else is secondary
slide-12
SLIDE 12

Example

c

2012– Andrei Alexandrescu.

12 / 59

#include <iostream> int main() { std::cout << "Hello, world!" << std::endl; }

  • Incorrect
  • Inefficient
  • Relies on one exceedingly subtle language rule to work
  • Surreptitiously uses inversion of control
  • Works due to an exception disallowed everywhere else
slide-13
SLIDE 13

Memory model

c

2012– Andrei Alexandrescu.

13 / 59

  • Memory bedrock inherited largely from C
  • You know where most everything is
  • Exceptions:
  • Pointer to vtable
  • Pointer to parent class in virtual inheritance

schemes

  • Address of constructor/destructor
  • Offsets of members in some classes
  • Impacts:
  • Inherent efficiency
  • Approach to safety
slide-14
SLIDE 14

Underlying Machine

c

2012– Andrei Alexandrescu.

14 / 59

  • Most code predictably translates into either:
  • Simple machine code instructions
  • Direct function calls
  • Indirect function calls
  • That’s pretty much it!
  • Exceptions:
  • Constructor/destructor calls
  • Exception throwing, transporting, catching
slide-15
SLIDE 15

Constructor and destructor calls

c

2012– Andrei Alexandrescu.

15 / 59

  • Ctor calls + copy ctor calls == dtor calls
  • No ownership transfer semantics (C++11 fixes that)
  • Invariant is difficult to maintain
  • Very often spurious calls are present
  • Benchmark: 1-7 ctor calls for the same code

depending on compiler and optimization level

  • Geared toward value semantics, not polymorphism
slide-16
SLIDE 16

You don’t pay for what you don’t use

c

2012– Andrei Alexandrescu.

16 / 59

  • RTTI/dynamic_cast adds per-class overhead even

when never used.

  • Exceptions have non-zero costs even when never used
  • Impossible to specify “nothrow” modularly
  • Even C functions are assumed to throw!
  • All exceptions are catchable
  • Complicates most function frames
slide-17
SLIDE 17

Building Abstraction

c

2012– Andrei Alexandrescu.

17 / 59

slide-18
SLIDE 18

What is abstraction?

c

2012– Andrei Alexandrescu.

18 / 59

slide-19
SLIDE 19

What is abstraction?

c

2012– Andrei Alexandrescu.

18 / 59

Selective ignorance

slide-20
SLIDE 20

Why is selective ignorance good?

c

2012– Andrei Alexandrescu.

19 / 59

slide-21
SLIDE 21

Why is selective ignorance good?

c

2012– Andrei Alexandrescu.

19 / 59

Allows you to ignore details

slide-22
SLIDE 22

Why is ignoring details good?

c

2012– Andrei Alexandrescu.

20 / 59

slide-23
SLIDE 23

Why is ignoring details good?

c

2012– Andrei Alexandrescu.

20 / 59

MODULARITY

slide-24
SLIDE 24

Surprising fact #1

c

2012– Andrei Alexandrescu.

21 / 59

Most software engineering tools and techniques ultimately aim at improving modularity

slide-25
SLIDE 25

Modularity

c

2012– Andrei Alexandrescu.

22 / 59

  • Type systems
  • Functions
  • Information hiding
  • Encapsulation
  • Objects
  • Design patterns
  • Lazy evaluation
  • Lambdas
  • Monads
  • Memcache!
  • . . .
slide-26
SLIDE 26

Modularity through abstraction

c

2012– Andrei Alexandrescu.

23 / 59

  • Abstraction is a powerful modularity mechanism
  • Power in nomenclature
  • Stable: abstractions < details
  • Allows keeping details in separation
  • Allows improvement of details in separation
slide-27
SLIDE 27

Abstraction liabilities

c

2012– Andrei Alexandrescu.

24 / 59

  • Efficiency cost (“abstraction friction”)
  • Cognitive cost
  • Verbosity cost
  • Informational cost
  • Leakiness
slide-28
SLIDE 28

C++ functions as abstraction mechanism

c

2012– Andrei Alexandrescu.

25 / 59

  • Low barrier of entry, starting at $0
  • Eager evaluation
  • Genericity (templates)
  • Specialization (template specialization)
  • Ambiguous input and output parameters
  • Uninformative signatures
  • No escaping information
  • No purity information
  • No safety information
  • No exception information
  • People use convention for all of the above
slide-29
SLIDE 29

Example: find item in array, work with it

c

2012– Andrei Alexandrescu.

26 / 59

vector<int> v; int e; ... for (int i = 0; i < v.size(); ++i) { if (v[i] == e) { ... /* do work */ ... break; } }

  • Relies on vector
  • Mixes searching details with work details
  • Difficult to improve modularly
slide-30
SLIDE 30

Example: find item in array, work with it

c

2012– Andrei Alexandrescu.

27 / 59

vector<int> v; int e; ... auto i = find(v.begin(), v.end(), e); if (i != v.end()) { ... /* do work */ ... }

  • Works with many topologies
  • Searching details separated from work details
  • Can be improve modularly
slide-31
SLIDE 31

find can be improved in isolation

c

2012– Andrei Alexandrescu.

28 / 59

template <class RIt, class V> RIt find(RIt b, RIt e, const V& v) { for (; (e - b) & 3; ++b) { if (*b == v) return b; } for (; b != e; b += 4) { if (*b == v) return b; if (b[1] == v) return b + 1; if (b[2] == v) return b + 2; if (b[3] == v) return b + 3; } }

slide-32
SLIDE 32

Good functional abstractions

c

2012– Andrei Alexandrescu.

29 / 59

  • Address frequent (ENFORCE) or specific

(multiwayUnion) intent

  • Sound-bite name (verb); easy to talk about
  • Express inputs, outputs, lifetime, and ownership
  • Hide operational details; easy to describe in one

sentence

  • Generally applicable; do not commit to irrelevant details

(find)

  • Do not treat complexity as a detail
slide-33
SLIDE 33

Building abstractions with

  • bjects

c

2012– Andrei Alexandrescu.

30 / 59

slide-34
SLIDE 34

C++ classes

c

2012– Andrei Alexandrescu.

31 / 59

  • Class is the unit of encapsulation in C++
  • Access control applies at class level
  • Methods and friend functions have access to everything

inside the class

  • Not the base class
  • Key point: multiple instances of the class
  • Key point: information hiding through data

encapsulation

slide-35
SLIDE 35

Class methods vs. free functions

c

2012– Andrei Alexandrescu.

32 / 59

  • Conventional wisdom: methods are cool, free functions

are so 1960s

  • Yet:
  • Free functions improve encapsulation over methods
  • Free functions may be more general
  • Free functions decouple better
  • Free functions support conversions on their

left-hand argument

slide-36
SLIDE 36

Surprising fact #2

c

2012– Andrei Alexandrescu.

33 / 59

Making a function a method should be your last, not first, choice

slide-37
SLIDE 37

c

2012– Andrei Alexandrescu.

34 / 59

slide-38
SLIDE 38

Value vs. reference semantics

c

2012– Andrei Alexandrescu.

35 / 59

  • Per discussion in Part 1:
  • Equal copies algebraically equivalent (think int)
  • Polymorphic values have “personality”—one

instance, many referents

  • Always decide early on value vs. reference
  • Never define ambiguous-gender types
  • Exception: exceptions
slide-39
SLIDE 39

Archetypal value

c

2012– Andrei Alexandrescu.

36 / 59

class V { public: V(); // nothrow V(const V & rhs); // deep copy ~V(); V& operator=(const V& rhs); ... };

slide-40
SLIDE 40

Archetypal reference

c

2012– Andrei Alexandrescu.

37 / 59

class R { R& operator=(const R& rhs); // not defined protected: R(const R & rhs); // optional; deep copy public: R(); // optional virtual ~R(); // essential virtual unique_ptr<R> clone() { CHECK(typeid(*this) == typeid(R)); return new R(*this); } ... };

slide-41
SLIDE 41

The C++ Standard Library

c

2012– Andrei Alexandrescu.

38 / 59

slide-42
SLIDE 42

The C++ Standard Library

c

2012– Andrei Alexandrescu.

39 / 59

  • “The reptilian brain:” The C Standard Library
  • “Limbic system:” iostreams, string, complex, . . .
  • “Neocortex:” The Standard Template Library
slide-43
SLIDE 43

The STL

c

2012– Andrei Alexandrescu.

40 / 59

  • Arguably the best software library ever conceived
  • Focuses on asking the right question
  • “What is the essence of the fundamental algorithms

and containers?”

  • Arguably most everything else is aftermath
  • Abstract: Leaving room for redesign is fail
  • Frictionless: Leaving incentive for reimplementation is

fail

slide-44
SLIDE 44

Bottleneck design

c

2012– Andrei Alexandrescu.

41 / 59

  • Many algorithms, no categorization
  • Few iterators, strict categorization
  • input
  • output
  • forward
  • bidirectional
  • random access
  • Many containers, loose categorization
slide-45
SLIDE 45

STL algorithms

c

2012– Andrei Alexandrescu.

42 / 59

  • Many fundamental algorithms
  • sorting
  • searching
  • accumulation
  • transformation
  • Never operate directly on containers
  • Never affect topology, only data
slide-46
SLIDE 46

STL containers

c

2012– Andrei Alexandrescu.

43 / 59

  • No hierarchy
  • Federation of loosely categorized objects
  • Linear: vector, list, deque
  • Associative: set, map, unordered map
  • Choice is by complexity/validity guarantees
slide-47
SLIDE 47

The star of STL: iterators

c

2012– Andrei Alexandrescu.

44 / 59

  • Mediate traffic between algorithms and containers
  • Generalization of pointers
  • Input: i == j, *i, ++i
  • Forward: Input, i = j
  • Bidirectional: Forward, --i
  • Random access: Bidirectional, i[n], i + n
slide-48
SLIDE 48

What do you need for. . .

c

2012– Andrei Alexandrescu.

45 / 59

  • Linear search
  • Subsequence brute force search
  • Boyer-Moore search
  • Quicksort
  • Bring-to-front
  • Stable remove
  • Unstable remove
slide-49
SLIDE 49

STL assets

c

2012– Andrei Alexandrescu.

46 / 59

  • Abstraction power
  • Efficiency
  • Offers a model for other algorithms, containers, and

iterators

  • Plays perfectly into C++’s strengths
  • Most other languages cannot implement STL
  • This is remarkable
slide-50
SLIDE 50

STL liabilities

c

2012– Andrei Alexandrescu.

47 / 59

  • Lack of lambda functions makes many algorithms

tenuous

  • Fixed in C++11
  • Allocator design inadequate
  • Syntax relatively verbose
  • “C++ complete”
  • Ethos impossible to understand outside of C++
slide-51
SLIDE 51

Practical advice

c

2012– Andrei Alexandrescu.

48 / 59

  • Prefer STL to ad-hoc containers
  • Prefer our containers to the default ones
  • Prefer iterators to indexed access
  • Understand, use, and extend algorithms
  • Avoid dogma beyond all else
slide-52
SLIDE 52

Generic Programming

c

2012– Andrei Alexandrescu.

49 / 59

slide-53
SLIDE 53

What is generic programming?

c

2012– Andrei Alexandrescu.

50 / 59

slide-54
SLIDE 54

What is generic programming?

c

2012– Andrei Alexandrescu.

50 / 59

Generic Programming is the endeavor of finding the most abstract expression of a computation without losing its essence or efficiency.

slide-55
SLIDE 55

Symptoms of generic programming deficit

c

2012– Andrei Alexandrescu.

51 / 59

  • “Same drama, different stage”
  • Implement same algorithm several times
  • Design with high-level notions but implement from first

principles

  • Can’t reuse a function without changing a few details
  • Similar methods in unrelated hierarchies
slide-56
SLIDE 56

C++ for generic programming?

c

2012– Andrei Alexandrescu.

52 / 59

  • + Template engine abstracts at no/low cost
  • + Post-hoc specialization possible
  • + Good efficiency to begin with
  • + No commitment to one paradigm
  • − Ad-hoc features, no unifying arc
  • − Uses vast array of odd features
slide-57
SLIDE 57

Example: specializing on iterator

c

2012– Andrei Alexandrescu.

53 / 59

  • Recall from earlier:

template <class RIt, class V> RIt find(RIt b, RIt e, const V& v) { for (; (e - b) & 3; ++b) { if (*b == v) return b; } for (; b != e; b += 4) { if (*b == v) return b; if (b[1] == v) return b + 1; if (b[2] == v) return b + 2; if (b[3] == v) return b + 3; } }

  • How do we specialize find only for random-access

iterators?

slide-58
SLIDE 58

Dispatching on category

c

2012– Andrei Alexandrescu.

54 / 59

  • Classic technique: “tag dispatching”
  • Not so classic: dispatch is static
  • Now defining the base version working for all iterators

template <class It, class V> It find(It b, It e, const V& v, std::input_iterator_tag) { for (; e != b; ++b) { if (*b == v) return b; } }

slide-59
SLIDE 59

Dispatching on category

c

2012– Andrei Alexandrescu.

55 / 59

  • Now defining the specialized version

template <class It, class V> It find(It b, It e, const V& v, std::random_access_iterator_tag) { for (; (e - b) & 3; ++b) { if (*b == v) return b; } for (; b != e; b += 4) { if (*b == v) return b; if (b[1] == v) return b + 1; if (b[2] == v) return b + 2; if (b[3] == v) return b + 3; } }

slide-60
SLIDE 60

The Dispatcher

c

2012– Andrei Alexandrescu.

56 / 59

template <class It, class V> It find(It b, It e, const V& v) { return find(b, e, v, typename iterator_traits<It>::iterator_category()); }

slide-61
SLIDE 61

Testing 1-2-3

c

2012– Andrei Alexandrescu.

57 / 59

int main() { vector<int> vec; list<int> lst; find(vec.begin(), vec.end(), 42); find(lst.begin(), lst.end(), 42); }

slide-62
SLIDE 62

We’re about done!

  • C++
  • Prolegomena
  • Rules of Engagement

Why? C++’s Computational Model Building Abstraction Building abstractions with objects The C++ Standard Library Generic Programming We’re about done!

  • c

2012– Andrei Alexandrescu.

58 / 59

slide-63
SLIDE 63

c

2012– Andrei Alexandrescu.

59 / 59

Questions ?