From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

146
From Zero to Iterators Building and Extending the Iterator Hierarchy in a Modern, Multicore World Patrick M. Niedzielski pniedzielski.net

Transcript of From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Page 1: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

From Zero to IteratorsBuilding and Extending the Iterator Hierarchy in a Modern, Multicore World

Patrick M. Niedzielskipniedzielski.net

Page 2: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

0

Page 3: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

I’ve heard of iterators before.

0

Page 4: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

I’ve used iterators before.

0

Page 5: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

I like iterators.

0

Page 6: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

I love iterators.

0

Page 7: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

I really love iterators.

0

Page 8: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

I think iterators are fundamental to computer science.

0

Page 9: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

0

Page 10: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

The goal

✓ I’ve heard of iterators before.✓ I’ve used iterators before.(✓) I love iterators.× I think iterators are fundamental to computer science.

1

Page 11: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

The goal

✓ I’ve heard of iterators before.✓ I’ve used iterators before.(✓) I love iterators.× I think iterators are fundamental to computer science. (Ask me offline!)

1

Page 12: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

How we’ll get there

Iterators 101: Introduction to IteratorsIterators 301: Advanced Iterators

Generic Programming

2

Page 13: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

How we’ll get there

Iterators 101: Introduction to IteratorsIterators 301: Advanced Iterators

Generic Programming

2

Page 14: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

How we’ll get there

Iterators 101: Introduction to IteratorsIterators 301: Advanced Iterators

Generic Programming

2

Page 15: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

What this talk is not

• An introduction to the STL.• A comprehensive guide to Concepts Lite.

3

Page 16: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

A note about questions

4

Page 17: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Iterators 101

Page 18: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

A simple starting point

template <typename T>T* copy(T const* in, T const* in_end,

T* out, T* out_end){

while (in != in_end && out != out_end) *out++ = *in++;return out;

}

5

Page 19: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

A simple starting point

auto source = array<T, 5>{ /* ... */ };auto destination = array<T, 10>{ /* ... */ };

copy(&source[0], &source[0] + size(source),&destination[0], &destination[0] + size(destination)

);

6

Page 20: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

But we don’t just deal with arrays…

template <typename T>struct node{

T value;node* next;

};

T{…} T{…} T{…} T{…} T{…} ∅

7

Page 21: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

But we don’t just deal with arrays…

template <typename T>struct node{

T value;node* next;

};

T{…} T{…} T{…} T{…} T{…} ∅

7

Page 22: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

But we don’t just deal with arrays…

template <typename T>node<T>* copy(node<T> const* in, node<T> const* in_end,

node<T>* out, node<T>* out_end){

while (in != in_end && out != out_end) {out->value = in->value;in = in->next;out = out->next;

}return out;

}

8

Page 23: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

But we don’t just deal with arrays…

template <typename T>T* copy(node<T> const* in, node<T> const* in_end,

T* out, T* out_end){

while (in != in_end && out != out_end) {*out++ = in->value;in = in->next;

}return out;

}

9

Page 24: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

But we don’t just deal with arrays…

template <typename T>ostream& copy(T const* in, T const* in_end, ostream& out){

while (in != in_end && out) out << *in++;return out;

}

10

Page 25: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

So what?

10

Page 26: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

So what?

• Array→ Array• Singly-Linked List→ Singly-Linked List• Singly-Linked List→ Array• Array→ Stream

But also,• Array→ Singly-Linked List• Singly-Linked List→ Stream• Stream→ Array• Stream→ Singly-Linked List• Stream→ Stream

3× 3 = 9 functions

11

Page 27: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

So what?

• Array→ Array• Singly-Linked List→ Singly-Linked List• Singly-Linked List→ Array• Array→ Stream

But also,• Array→ Singly-Linked List• Singly-Linked List→ Stream• Stream→ Array• Stream→ Singly-Linked List• Stream→ Stream

3× 3 = 9 functions

11

Page 28: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

So what?

4× 4 = 16 functions

12

Page 29: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

So what?

5× 5 = 25 functions

13

Page 30: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

So what?

6× 6 = 36 functions

14

Page 31: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

So what?

7× 7 = 49 functions

15

Page 32: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

So what?

7× 7× 2 = 98 functions!

16

Page 33: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

So what?

7× 7× 3 = 147 functions!

17

Page 34: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

So what?

7× 7× 4 = 196 functions!

18

Page 35: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

So what?

m data structures, n algorithms,

n ·m2 functions!

19

Page 36: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

We must be missing something.

19

Page 37: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Let’s back up.

template <typename T>output copy(input sequence, output sequence){

while (input not empty && output not empty) {write output = read input;increment output;increment input;

}return output;

}

20

Page 38: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Let’s back up.

template <typename T>output copy(input sequence, output sequence){

while (input not empty && output not empty) {write output = read input;increment output;increment input;

}return output;

}

20

Page 39: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Generalization

• T const*• node<T> const*• istream&• …

• T*• node<T>*• ostream&• …

Iterators

21

Page 40: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Generalization

• T const*• node<T> const*• istream&• …

• T*• node<T>*• ostream&• …

Iterators

21

Page 41: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Generalization

• T const*• node<T> const*• istream&• …

• T*• node<T>*• ostream&• …

Iterators

21

Page 42: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Generalization

template <typename T>output copy(input sequence, output sequence){

while (input not empty && output not empty) {write output = read input;increment output;increment input;

}return output;

}

22

Page 43: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Generalization

template <typename InputIterator, typename OutputIterator>OutputIterator copy(InputIterator in, InputIterator in_end

OutputIterator out, OutputIterator out_end){

while (in != in_end && out != out_end) {write output = read input;increment output;increment input;

}return out;

}

23

Page 44: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Generalization

template <typename InputIterator, typename OutputIterator>OutputIterator copy(InputIterator in, InputIterator in_end

OutputIterator out, OutputIterator out_end){

while (in != in_end && out != out_end) {write output = source(in); // e.g., *inincrement output;increment input;

}return out;

}

24

Page 45: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Generalization

template <typename InputIterator, typename OutputIterator>OutputIterator copy(InputIterator in, InputIterator in_end

OutputIterator out, OutputIterator out_end){

while (in != in_end && out != out_end) {sink(out) = source(in); // e.g., *outincrement output;increment input;

}return out;

}

25

Page 46: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Generalization

template <typename InputIterator, typename OutputIterator>OutputIterator copy(InputIterator in, InputIterator in_end

OutputIterator out, OutputIterator out_end){

while (in != in_end && out != out_end) {sink(out) = source(in);out = successor(out);in = successor(in);

}return out;

}

26

Page 47: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Generalization

inline auto const& source(auto const* p) { return *p; }inline auto const& source(node<auto> const* p) { return p->value; }

inline auto& sink(auto* p) { return *p; }inline auto& sink(node<auto>* p) { return p->value; }

inline auto successor(auto const* p) { return p + 1; }inline auto successor(node<auto> const* p) { return p->next; }

27

Page 48: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Let’s get formal.

27

Page 49: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

What do we need?

template <typename InputIterator, typename OutputIterator>OutputIterator copy(InputIterator in, InputIterator in_end

OutputIterator out, OutputIterator out_end){

while (in != in_end && out != out_end) {sink(out) = source(in);out = successor(out);in = successor(in);

}return out;

}

Equality Comparison

28

Page 50: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

What do we need?

template <typename InputIterator, typename OutputIterator>OutputIterator copy(InputIterator in, InputIterator in_end

OutputIterator out, OutputIterator out_end){

while (in != in_end && out != out_end) {sink(out) = source(in);out = successor(out);in = successor(in);

}return out;

}

Equality Comparison

28

Page 51: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

What do we need?

template <typename InputIterator, typename OutputIterator>OutputIterator copy(InputIterator in, InputIterator in_end

OutputIterator out, OutputIterator out_end){

while (in != in_end && out != out_end) {sink(out) = source(in);out = successor(out);in = successor(in);

}return out;

}

Assignment

29

Page 52: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

What do we need?

template <typename InputIterator, typename OutputIterator>OutputIterator copy(InputIterator in, InputIterator in_end

OutputIterator out, OutputIterator out_end){

while (in != in_end && out != out_end) {sink(out) = source(in);out = successor(out);in = successor(in);

}return out;

}

Construction

30

Page 53: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

What do we need?

template <typename InputIterator, typename OutputIterator>OutputIterator copy(InputIterator in, InputIterator in_end

OutputIterator out, OutputIterator out_end){

while (in != in_end && out != out_end) {sink(out) = source(in);out = successor(out);in = successor(in);

}return out;

}

Destruction

31

Page 54: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

What do we need?

template <typename InputIterator, typename OutputIterator>OutputIterator copy(InputIterator in, InputIterator in_end

OutputIterator out, OutputIterator out_end){

while (in != in_end && out != out_end) {sink(out) = source(in);out = successor(out);in = successor(in);

}return out;

}

successor()

32

Page 55: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

What do we need?

template <typename InputIterator, typename OutputIterator>OutputIterator copy(InputIterator in, InputIterator in_end

OutputIterator out, OutputIterator out_end){

while (in != in_end && out != out_end) {sink(out) = source(in);out = successor(out);in = successor(in);

}return out;

}

source()

33

Page 56: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

What do we need?

template <typename InputIterator, typename OutputIterator>OutputIterator copy(InputIterator in, InputIterator in_end

OutputIterator out, OutputIterator out_end){

while (in != in_end && out != out_end) {sink(out) = source(in);out = successor(out);in = successor(in);

}return out;

}

sink()

34

Page 57: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

What do we need?

InputIterator

Regular

• Constructible• Destructible• Assignable• Equality Comparable

Iterator

• successor()

Readable

• source()

OutputIterator

Regular

• Constructible• Destructible• Assignable• Equality Comparable

Iterator

• successor()

Writable

• sink()

35

Page 58: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

What do we need?

InputIterator

Regular• Constructible• Destructible• Assignable• Equality Comparable

Iterator

• successor()

Readable

• source()

OutputIterator

Regular• Constructible• Destructible• Assignable• Equality Comparable

Iterator

• successor()

Writable

• sink()

35

Page 59: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

What do we need?

InputIterator

Regular• Constructible• Destructible• Assignable• Equality Comparable

Iterator• successor()

Readable

• source()

OutputIterator

Regular• Constructible• Destructible• Assignable• Equality Comparable

Iterator• successor()

Writable

• sink()

35

Page 60: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

What do we need?

InputIterator

Regular• Constructible• Destructible• Assignable• Equality Comparable

Iterator• successor()

Readable• source()

OutputIterator

Regular• Constructible• Destructible• Assignable• Equality Comparable

Iterator• successor()

Writable• sink()

35

Page 61: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Concepts!

35

Page 62: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Concepts!

template <typename T>concept bool Concept = /* constexpr boolean expression */;

36

Page 63: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Concepts!

template <typename T>concept bool Regular =

is_default_constructible_v<T>&& is_copy_constructible_v<T>&& is_destructible_v<T>&& is_copy_assignable_v<T>&& is_equality_comparable_v<T>;

Doesn’t exist.

37

Page 64: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Concepts!

template <typename T>concept bool Regular =

is_default_constructible_v<T>&& is_copy_constructible_v<T>&& is_destructible_v<T>&& is_copy_assignable_v<T>&& is_equality_comparable_v<T>;

Doesn’t exist.

37

Page 65: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Concepts!

template <typename T>concept bool Regular =

is_default_constructible_v<T>&& is_copy_constructible_v<T>&& is_destructible_v<T>&& is_copy_assignable_v<T>&& is_equality_comparable_v<T>;

Doesn’t exist.

37

Page 66: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Concepts!

template <typename T>concept bool Regular =

is_default_constructible_v<T>&& is_copy_constructible_v<T>&& is_destructible_v<T>&& is_copy_assignable_v<T>&& ∀x,y ∈ T:

1. x == y can be used in boolean contexts2. == induces an equivalence relation on T3. Iff x == y, x and y represent the same value

;

38

Page 67: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Concepts!

template <typename T>concept bool Regular =

is_default_constructible_v<T>&& is_copy_constructible_v<T>&& is_destructible_v<T>&& is_copy_assignable_v<T>&& requires(T x, T y) {

1. x == y can be used in boolean contexts2. == induces an equivalence relation on T3. Iff x == y, x and y represent the same value

};

39

Page 68: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Concepts!

template <typename T>concept bool Regular =

is_default_constructible_v<T>&& is_copy_constructible_v<T>&& is_destructible_v<T>&& is_copy_assignable_v<T>&& requires(T x, T y) {

{ x == y } -> bool;2. == induces an equivalence relation on T3. Iff x == y, x and y represent the same value

};

40

Page 69: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Concepts!

template <typename T>concept bool Regular =

is_default_constructible_v<T>&& is_copy_constructible_v<T>&& is_destructible_v<T>&& is_copy_assignable_v<T>&& requires(T x, T y) {

{ x == y } -> bool;// == induces an equivalence relation on T// Iff x == y, x and y represent the same value

};

41

Page 70: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Concepts!

template <typename T>concept bool Readable =

requires (T x) {typename value_type<T>;{ source(x) } -> value_type<T> const&; // O(1)

};

42

Page 71: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Concepts!

template <typename T>concept bool Writable =

requires (T x) {typename value_type<T>;{ sink(x) } -> value_type<T>&; // O(1)

};

43

Page 72: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Concepts!

template <typename I>concept bool Iterator =

Regular<I> &&requires (I i) {

{ successor(i) } -> I; // O(1)// successor() may mutate other iterators.

};

44

Page 73: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Concepts!

template <typename InputIterator, typename OutputIterator>OutputIterator copy(InputIterator in, InputIterator in_end

OutputIterator out, OutputIterator out_end){

while (in != in_end && out != out_end) {sink(out) = source(in);out = successor(out);in = successor(in);

}return out;

}

45

Page 74: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Concepts!

template <typename InputIterator, typename OutputIterator>requires Iterator<InputIterator>

&& Readable<InputIterator>&& Iterator<OutputIterator>&& Writable<OutputIterator>

OutputIterator copy(InputIterator in, InputIterator in_endOutputIterator out, OutputIterator out_end)

{while (in != in_end && out != out_end) {

sink(out) = source(in);out = successor(out);in = successor(in);

}return out;

}

46

Page 75: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Concepts!

template <typename In, typename Out>requires Iterator<In>

&& Readable<In>&& Iterator<Out>&& Writable<Out>

Out copy(In in, In in_end, Out out, Out out_end){

while (in != in_end && out != out_end) {sink(out) = source(in);out = successor(out);in = successor(in);

}return out;

}

47

Page 76: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Concepts!

template <Iterator In, Iterator Out>requires Readable<In> && Writable<Out>

Out copy(In in, In in_end, Out out, Out out_end){

while (in != in_end && out != out_end) {sink(out) = source(in);out = successor(out);in = successor(in);

}return out;

}

48

Page 77: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

More algorithms

template <Iterator It>requires Writable<It>

void fill(It it, It it_end, value_type<It> const& x){

while (in != in_end) {sink(out) = x;it = successor(it);

}}

49

Page 78: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

More algorithms

template <Iterator It, Function<value_type<It>, value_type<It>> Op>requires Readable<It>

auto fold(It it, It it_end, value_type<It> acc, Op op){

while (in != in_end) {acc = op(acc, source(it));it = successor(it);

}return acc;

}

50

Page 79: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

More algorithms

template <Iterator It>requires Readable<It>

It find_first(It it, It it_end, value_type<It> const& value){

while (it != it_end && source(it) != value)it = successor(it);

return it;}

51

Page 80: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Moving Forward

template <Iterator It>requires Readable<It>

It max_element(It it, It it_end){

auto max_it = it;while (it != it_end) {

if (source(it) > source(max_it)) max_it = it;it = successor(it);

}return max_it;

}

No!

52

Page 81: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Moving Forward

template <Iterator It>requires Readable<It>

It max_element(It it, It it_end){

auto max_it = it;while (it != it_end) {

if (source(it) > source(max_it)) max_it = it;it = successor(it);

}return max_it;

}

No!

52

Page 82: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Moving Forward

template <Iterator It>requires Readable<It>

It max_element(It it, It it_end){

auto max_it = it;while (it != it_end) {

if (source(it) > source(max_it)) max_it = it;it = successor(it);

}return max_it;

}

No!52

Page 83: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Moving Forward

template <typename I>concept bool Iterator =

Regular<I> &&requires (I i) {

{ successor(i) } -> I; // O(1)// successor may mutate other iterators

};

53

Page 84: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Moving Forward

template <typename I>concept bool Iterator =

Regular<I> &&requires (I i) {

{ successor(i) } -> I; // O(1)// successor may mutate other iterators

};

53

Page 85: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Moving Forward

template <typename I>concept bool ForwardIterator =

Regular<I> &&requires (I i) {

{ successor(i) } -> I; // O(1)

};

Multi-pass Guarantee

54

Page 86: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Moving Forward

template <typename I>concept bool ForwardIterator =

Regular<I> &&requires (I i) {

{ successor(i) } -> I; // O(1)

};

Multi-pass Guarantee

54

Page 87: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Moving Forward

template <ForwardIterator It>requires Readable<It>

It max_element(It it, It it_end){

auto max_it = it;while (it != it_end) {

if (source(it) > source(max_it)) max_it = it;it = successor(it);

}return max_it;

}

55

Page 88: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Moving Forward

PropositionIf a type T models ForwardIterator, it also models Iterator.

A ForwardIterator is just an Iterator that doesn’t mutate other iterators insuccessor()!

56

Page 89: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Moving Forward

PropositionIf a type T models ForwardIterator, it also models Iterator.

A ForwardIterator is just an Iterator that doesn’t mutate other iterators insuccessor()!

56

Page 90: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Backing Up

template <??? I>requires Readable<I> && Writable<I>

I reverse(I it_begin, I it_end){

while (it_begin != it_end) {it_end = predecessor(it_end);if (it_begin == it_end) break;

auto temp = source(it_end);sink(it_end) = source(it_begin);sink(it_begin) = temp;

it_begin = successor(it_begin);}

}

57

Page 91: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Backing Up

template <??? I>requires Readable<I> && Writable<I>

I reverse(I it_begin, I it_end){

while (it_begin != it_end) {it_end = predecessor(it_end);if (it_begin == it_end) break;

auto temp = source(it_end);sink(it_end) = source(it_begin);sink(it_begin) = temp;

it_begin = successor(it_begin);}

} 57

Page 92: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Backing Up

template <??? I>requires Readable<I> && Writable<I>

I reverse(I it_begin, I it_end){

while (it_begin != it_end) {it_end = predecessor(it_end);if (it_begin == it_end) break;

auto temp = source(it_end);sink(it_end) = source(it_begin);sink(it_begin) = temp;

it_begin = successor(it_begin);}

} 57

Page 93: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Backing Up

template <typename I>concept bool BidirectionalIterator =

Regular<I> &&requires (I i) {

{ successor(i) } -> I; // O(1){ predecessor(i) } -> I; // O(1)

// i == predecessor(successor(i));};

58

Page 94: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Backing Up

template <BidirectionalIterator I>requires Readable<I> && Writable<I>

I reverse(I it_begin, I it_end){

while (it_begin != it_end) {it_end = predecessor(it_end);if (it_begin == it_end) break;

auto temp = source(it_end);sink(it_end) = source(it_begin);sink(it_begin) = temp;

it_begin = successor(it_begin);}

} 59

Page 95: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Backing Up

template <BidirectionalIterator I>requires Readable<I> && Writable<I>

I reverse(I it_begin, I it_end){

while (it_begin != it_end) {it_end = predecessor(it_end);if (it_begin == it_end) break;

auto temp = source(it_end);sink(it_end) = source(it_begin);sink(it_begin) = temp;

it_begin = successor(it_begin);}

} 60

Page 96: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Backing Up

PropositionIf a type T models BidirectionalIterator, it also modelsForwardIterator.

A BidirectionalIterator has a successor() function that does notmutate other iterators.

61

Page 97: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Backing Up

PropositionIf a type T models BidirectionalIterator, it also modelsForwardIterator.

A BidirectionalIterator has a successor() function that does notmutate other iterators.

61

Page 98: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Backing Up

PropositionIf a type T models BidirectionalIterator, its dual also modelsBidirectionalIterator.

Let’s define a type whose successor() is our old predecessor() and whosepredecessor() is our old successor(). This new type also models

BidirectionalIterator.

We call the dual of a BidirectionalIterator a reverse iterator.

62

Page 99: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Backing Up

PropositionIf a type T models BidirectionalIterator, its dual also modelsBidirectionalIterator.

Let’s define a type whose successor() is our old predecessor() and whosepredecessor() is our old successor(). This new type also models

BidirectionalIterator.

We call the dual of a BidirectionalIterator a reverse iterator.

62

Page 100: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Backing Up

PropositionIf a type T models BidirectionalIterator, its dual also modelsBidirectionalIterator.

Let’s define a type whose successor() is our old predecessor() and whosepredecessor() is our old successor(). This new type also models

BidirectionalIterator.

We call the dual of a BidirectionalIterator a reverse iterator.

62

Page 101: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Jumping Around

template <ForwardIterator It>void increment(It& i, size_t n){

// Precondition: n >= 0for (auto i = 0; i < n; ++i) i = successor(i);

}

void increment(auto*& i, size_t n){

// Precondition: n >= 0i += n;

}

63

Page 102: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Jumping Around

template <ForwardIterator It>void increment(It& i, size_t n){

// Precondition: n >= 0for (auto i = 0; i < n; ++i) i = successor(i);

}

void increment(auto*& i, size_t n){

// Precondition: n >= 0i += n;

}

63

Page 103: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Jumping Around

template <ForwardIterator It>void increment(It& i, size_t n){

// Precondition: n >= 0for (auto i = 0; i < n; ++i) i = successor(i);

}

void increment(auto*& i, size_t n){

// Precondition: n >= 0i += n;

}

63

Page 104: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Jumping Around

template <BidirectionalIterator It>void decrement(It& i, size_t n){

// Precondition: n >= 0for (auto i = 0; i < n; ++i) i = predecessor(i);

}

void decrement(auto*& i, size_t n){

// Precondition: n >= 0i -= n;

}

64

Page 105: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Jumping Around

template <typename I>concept bool RandomAccessIterator =

Regular<I>&& WeaklyOrdered<I>&& requires (I i, I j, size_t n) {

{ i + n } -> I; // O(1)// i + 0 == i if n == 0// i + n == successor(i) + n - 1 if n > 0// i + n == predecessor(i) + n + 1 if n < 0

{ i - n } -> I; // O(1)// i - 0 == i if n == 0// i - n == predecessor(i) - (n - 1) if n > 0// i - n == successor(i) - (n + 1) if n < 0

{ i - j } -> size_t; // O(1)// i + (i - j) = i

};65

Page 106: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Jumping Around

template <RandomAccessIterator It>requires Readable<It> && WeaklyOrdered<value_type<It>>

I upper_bound(It it, It it_end, value_type<It> x){

// Base case.if (it == it_end) return it_end;

// mid_dist is always less than or equal to end - begin,// because of integer divisionauto mid_dist = (it_end - it) / 2;auto mid = it + mid_dist;

// Reduce problem size.if (source(mid) <= x) return upper_bound(mid + 1, it_end, x);else return upper_bound( it, mid + 1, x);

}66

Page 107: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Jumping Around

PropositionIf a type T models RandomAccessIterator, it also modelsBidirectionalIterator.

Let’s define successor() on an object x of type T to return x + 1. Similarly,let’s define predecessor() to return x - 1.

67

Page 108: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Jumping Around

PropositionIf a type T models RandomAccessIterator, it also modelsBidirectionalIterator.

Let’s define successor() on an object x of type T to return x + 1. Similarly,let’s define predecessor() to return x - 1.

67

Page 109: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

The story so far

Iterator

Forward

Bidir

Random

68

Page 110: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Extending the Iterator Hierarchy

Page 111: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Pop Quiz!

68

Page 112: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Can I memmove a RandomAccess sequence of bytes?

68

Page 113: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Let’s look at the concept

template <typename I>concept bool RandomAccessIterator =

Regular<I>&& WeaklyOrdered<I>&& requires (I i, I j, size_t n) {

{ i + n } -> I; // O(1)// i + 0 == i if n == 0// i + n == successor(i) + n - 1 if n > 0// i + n == predecessor(i) + n + 1 if n < 0

{ i - n } -> I; // O(1)// i - 0 == i if n == 0// i - n == predecessor(i) - (n - 1) if n > 0// i - n == successor(i) - (n + 1) if n < 0

{ i - j } -> size_t; // O(1)// i + (i - j) = i

};69

Page 114: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

No!

69

Page 115: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

A counterexample

template <Regular T>struct segmented_array {

vector< vector<T> > data;// where each inner vector except the last has size segsize

};

70

Page 116: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

A counterexample

template <Regular T>struct segmented_array_iterator {

vector<T>* spine_iter;size_t inner_index;

};

template <Regular T>segmented_array_iterator<T> operator+(

segmented_array_iterator<T> it, size_t n){

return segmented_array_iterator<T>{it.spine_iter + (it.inner_index + n) / segsize,(it.inner_index + n) % segsize

};} 71

Page 117: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

What does memmove need?

• Trivially copyable data, that is• contiguous in memory.

72

Page 118: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

What does memmove need?

• Trivially copyable data, that is

• contiguous in memory.

72

Page 119: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

What does memmove need?

• Trivially copyable data, that is• contiguous in memory.

72

Page 120: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

What does contiguous mean?

auto i = /* ... */;auto j = /* ... */;pointer_from(i + n) == pointer_from(i) + n;pointer_from(i - n) == pointer_from(i) - n;pointer_from(i - j) == pointer_from(i) - pointer_from(j);

There must be an homomorphism pointer_from that preserves the rangestructure.

73

Page 121: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

What does contiguous mean?

auto i = /* ... */;auto j = /* ... */;pointer_from(i + n) == pointer_from(i) + n;pointer_from(i - n) == pointer_from(i) - n;pointer_from(i - j) == pointer_from(i) - pointer_from(j);

There must be an homomorphism pointer_from that preserves the rangestructure.

73

Page 122: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

What does contiguous mean?

auto i = /* ... */;auto j = /* ... */;pointer_from(i + n) == pointer_from(i) + n;pointer_from(i - n) == pointer_from(i) - n;pointer_from(i - j) == pointer_from(i) - pointer_from(j);

There must be an homomorphism pointer_from that preserves the rangestructure.

73

Page 123: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

The simplest homomorphism

auto* pointer_from(auto* i) { return i; }

74

Page 124: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

The slightly less simple homomorphism

template <typename T>using base_offset_iterator = pair<T*, size_t>;

auto* pointer_from(base_offset_iterator<auto> i){

return i.first + i.second;}

75

Page 125: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Looks like we have a new concept!

template <typename T>concept bool ContiguousIterator =

RandomAccessIterator<T>&& requires (T i) {

typename value_type<T>;{ pointer_from(i) } -> value_type<T> const*;// pointer_from homomorphism preserves range// structure

};

76

Page 126: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Looks like we have a new concept!

template <ContiguousIterator In, ContiguousIterator Out>requires Readable<In> && Writable<Out>

&& is_same_v< value_type<In>, value_type<Out> >&& is_trivially_copyable_v< value_type<In> >

Out copy(In in, In in_end, Out out, Out out_end){

auto count = min( in_end - in, out_end - out );memmove(pointer_from(out), pointer_from(in), count);return out_end;

}

77

Page 127: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Segmentation Problems

template <Regular T>struct segmented_array {

vector< vector<T> > data;// where each inner vector except the last has size segsize

};

78

Page 128: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Segmentation Problems

template <Regular T>struct segmented_array {

vector< vector<T> > data;// where each inner vector except the last has size segsize

};

78

Page 129: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Segmentation Problems

template <SegmentedIterator In, Iterator Out>requires Readable<In> && Writable<Out>

Out copy(In in, In in_end, Out out, Out out_end){

auto seg = segment(in);auto seg_end = segment(in_end);

if (seg == seg_end) copy(local(in), local(in_end), out, out_end);else {

out = copy(local(in), end(seg), out, out_end);

seg = successor(seg);while (seg != seg_end) {

out = copy(begin(seg), end(seg), out, out_end);seg = successor(seg);

}return copy(begin(seg), local(in_end), out, out_end);

}} 79

Page 130: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Segmentation Problems

template <typename T>concept bool SegmentedIterator =

Iterator<T>&& requires (T i) {

typename local_iterator<T>;typename segment_iterator<T>;

requires Iterator<local_iterator>;requires Iterator<segment_iterator>;requires Range<segment_iterator>; // begin(), end()

{ local(i) } -> local_iterator<T>;{ segment(i) } -> segment_iterator<T>;

};80

Page 131: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Segmentation Problems

// Associated typestemplate <typename T>using local_iterator< segmented_array_iterator<T> > = T*;template <typename T>using segment_iterator< segmented_array_iterator<T> > = vector<T>*;

// Inner iterator range (dirty, to fit on slides!)auto begin(vector<auto>* vec) { return vec->begin(); }auto end(vector<auto>* vec) { return vec->end(); }

// Access functionsauto local(segmented_array_iterator<auto> it) {

return &it->spine_iter[it->inner_index];}auto segment(segmented_array_iterator<auto> it) {

return it->spine_iter;} 81

Page 132: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

SegmentedIterators are great for parallelization.

template <RandomAccessIterator In, SegmentedIterator Out>requires Readable<In> && Writable<Out>

&& RandomAccessIterator<Out>Out copy(In in, In in_end, Out out, Out out_end){

auto& task_pool = get_global_task_pool();

auto seg = segment(out);auto seg_end = segment(out_end);

if (seg == seg_end) {// ...

} else {// ...

}}

82

Page 133: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

SegmentedIterators are great for parallelization.

template <RandomAccessIterator In, SegmentedIterator Out>requires Readable<In> && Writable<Out>

&& RandomAccessIterator<Out>Out copy(In in, In in_end, Out out, Out out_end){

auto& task_pool = get_global_task_pool();

auto seg = segment(out);auto seg_end = segment(out_end);

if (seg == seg_end) {// ...

} else {// ...

}}

82

Page 134: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

SegmentedIterators are great for parallelization.

if (seg == seg_end) {return copy(in, in_end, local(out), local(out_end));

} else {// ...

}

83

Page 135: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

SegmentedIterators are great for parallelization.

} else {task_pool.add_task(copy, in, in_end, local(out), end(seg_end));

seg = successor(seg);in = in + min(in_end - in, end(seg_end) - local(out));while (seg != seg_end) {

task_pool.add_task(copy, in, in_end, begin(seg), end(seg));

seg = successor(seg);in = in + min(in_end - in, end(seg) - begin(seg));

}

task_pool.add_task(copy, in, in_end, begin(seg), local(out_end));return out + min(in_end - in, local(out_end) - begin(out));

}

84

Page 136: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

But wait!

84

Page 137: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

SegmentedIterators are great for parallelization.

84

Page 138: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

ContiguousIterators are great for bit blasting.

84

Page 139: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

What if we combine them?

84

Page 140: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Cache-awareness

template <typename T>concept bool CacheAwareIterator =

SegmentedIterator<T>&& ContiguousIterator<T>;

85

Page 141: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Cache-awareness

Since,

• each thread is fed its own set of cache lines,

• no two threads will be writing to the same cache lines,• no false-sharing.

86

Page 142: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Cache-awareness

Since,

• each thread is fed its own set of cache lines,• no two threads will be writing to the same cache lines,

• no false-sharing.

86

Page 143: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Cache-awareness

Since,

• each thread is fed its own set of cache lines,• no two threads will be writing to the same cache lines,• no false-sharing.

86

Page 144: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

86

Page 145: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

References

• Austern, Matthew H (1998). Segmented Iterators and Hierarchical Algorithms.In Proceedings of Generic Programming: International Seminar, DagstuhlCastle, Germany.

• Liber, Nevin (2014). N3884 — Contiguous Iterators: A Refinement of RandomAccess Iterators.

• Stepanov, Alexander and Paul McJones (2009). Elements of Programming.

87

Page 146: From Zero to Iterators: Building and Extending the Iterator Hierarchy in a Modern, Multicore World

Patrick M. Niedzielskipniedzielski.net

This work is licensed under a Creative Commons “Attribution 4.0 Inter-national” license.

87