Interruptible Iterators Jed Liu Aaron Kimball Andrew C. Myers - - PowerPoint PPT Presentation

interruptible iterators
SMART_READER_LITE
LIVE PREVIEW

Interruptible Iterators Jed Liu Aaron Kimball Andrew C. Myers - - PowerPoint PPT Presentation

Interruptible Iterators Jed Liu Aaron Kimball Andrew C. Myers Department of Computer Science Cornell University 33 rd ACM Symposium on Principles of Programming Languages 13 January, 2006 Jed Liu et al. Interruptible Iterators 1 Iteration


slide-1
SLIDE 1

Interruptible Iterators

Jed Liu Aaron Kimball Andrew C. Myers

Department of Computer Science Cornell University 33rd ACM Symposium on Principles of Programming Languages 13 January, 2006

Jed Liu et al. Interruptible Iterators 1

slide-2
SLIDE 2

Iteration Abstractions

Important to support iteration abstractions well

◮ Clients get on-demand access to elements of a

lazily-evaluated sequence

◮ Many mainstream languages support IAs

◮ e.g., C++, Python, Ruby ◮ Evolving to support better: C# 2.0, Java 1.5 ◮ Libraries too: Java Collections, Microsoft .NET

◮ Iterators are hard to implement

◮ Especially if they support imperative update

Interruptible iterators make IAs easier to implement

◮ Implemented as part of JMatch

Jed Liu et al. Interruptible Iterators 1

slide-3
SLIDE 3

Iterators: Easy to Use, Hard to Write

Easy to use: Java iterator interface

interface Iterator { boolean hasNext(); // Is there a next element? Object next(); // Return the next element void remove(); // Remove last element returned }

Can be hard to implement

◮ Iteration must continue where it last left off ◮ Iterator can become awkward state machine

Jed Liu et al. Interruptible Iterators 2

slide-4
SLIDE 4

Binary Tree Iterator Example in Java

class TreeIterator implements Iterator { Iterator subIterator; boolean hasNext; Object current; // 1 = Iterating through left child // 2 = Just yielded current node value // 3 = Iterating through right child int state; TreeIterator() { subIterator = Tree.this.left.iterator(); state = 1; current = preload(); } public boolean hasNext() { return hasNext; } public Object next() { if (!hasNext) throw new NoSuchElementException(); Object result = current; current = preload(); return result; } private Object preload() { loop: while (true) { switch (state) { case 1: case 3: hasNext = true; if (subIterator.hasNext()) { return subIterator.next(); } if (state == 1) { state = 2; return Tree.this.value; } hasNext = false; return null; case 2: subIterator = Tree.this.right.iterator(); state = 3; continue loop; } } } } Jed Liu et al. Interruptible Iterators 3

slide-5
SLIDE 5

Binary Tree Iterator Example in Java

class TreeIterator implements Iterator { Iterator subIterator; boolean hasNext; Object current; // 1 = Iterating through left child // 2 = Just yielded current node value // 3 = Iterating through right child int state; TreeIterator() { subIterator = Tree.this.left.iterator(); state = 1; current = preload(); } public boolean hasNext() { return hasNext; } public Object next() { if (!hasNext) throw new NoSuchElementException(); Object result = current; current = preload(); return result; } private Object preload() { loop: while (true) { switch (state) { case 1: case 3: hasNext = true; if (subIterator.hasNext()) { return subIterator.next(); } if (state == 1) { state = 2; return Tree.this.value; } hasNext = false; return null; case 2: subIterator = Tree.this.right.iterator(); state = 3; continue loop; } } } }

Even worse when you add support for updates Even worse when you add support for updates

Jed Liu et al. Interruptible Iterators 3

slide-6
SLIDE 6

Coroutine Iterators

◮ Increasingly popular: C# 2.0, Python, Ruby ◮ Iterator as a coroutine:

◮ Separate stack ◮ Iterator suspends execution by yielding values ◮ Client obtains more values by resuming iterator

Example: JMatch binary tree iterator class Node { int val; Node left, right; int elements() iterates(result) { foreach (int elt = left.elements()) yield elt; yield val; foreach (int elt = right.elements()) yield elt; } }

Jed Liu et al. Interruptible Iterators 4

slide-7
SLIDE 7

Coroutine Iterators

◮ Increasingly popular: C# 2.0, Python, Ruby ◮ Iterator as a coroutine:

◮ Separate stack ◮ Iterator suspends execution by yielding values ◮ Client obtains more values by resuming iterator

Example: JMatch binary tree iterator class Node { int val; Node left, right; int elements() iterates(result) { foreach (int elt = left.elements()) yield elt; yield val; foreach (int elt = right.elements()) yield elt; } }

elements is an iterator elements is an iterator

Jed Liu et al. Interruptible Iterators 4

slide-8
SLIDE 8

Coroutine Iterators

◮ Increasingly popular: C# 2.0, Python, Ruby ◮ Iterator as a coroutine:

◮ Separate stack ◮ Iterator suspends execution by yielding values ◮ Client obtains more values by resuming iterator

Example: JMatch binary tree iterator class Node { int val; Node left, right; int elements() iterates(result) { foreach (int elt = left.elements()) yield elt; yield val; foreach (int elt = right.elements()) yield elt; } }

Jed Liu et al. Interruptible Iterators 4

slide-9
SLIDE 9

Coroutine Iterators

◮ Increasingly popular: C# 2.0, Python, Ruby ◮ Iterator as a coroutine:

◮ Separate stack ◮ Iterator suspends execution by yielding values ◮ Client obtains more values by resuming iterator

Example: JMatch binary tree iterator class Node { int val; Node left, right; int elements() iterates(result) { foreach (int elt = left.elements()) yield elt; yield val; foreach (int elt = right.elements()) yield elt; } }

Jed Liu et al. Interruptible Iterators 4

slide-10
SLIDE 10

Coroutine Iterators

◮ Increasingly popular: C# 2.0, Python, Ruby ◮ Iterator as a coroutine:

◮ Separate stack ◮ Iterator suspends execution by yielding values ◮ Client obtains more values by resuming iterator

Example: JMatch binary tree iterator class Node { int val; Node left, right; int elements() iterates(result) { foreach (int elt = left.elements()) yield elt; yield val; foreach (int elt = right.elements()) yield elt; } }

Jed Liu et al. Interruptible Iterators 4

slide-11
SLIDE 11

Coroutine Iterators

class Node { int val; Node left, right; int elements() iterates(result) { foreach (int elt = left.elements()) yield elt; yield val; foreach (int elt = right.elements()) yield elt; } } Client elements elements elements yield yield yield

Jed Liu et al. Interruptible Iterators 4

slide-12
SLIDE 12

Coroutine Iterators

class Node { int val; Node left, right; int elements() iterates(result) { foreach (int elt = left.elements()) yield elt; yield val; foreach (int elt = right.elements()) yield elt; } } Client elements elements elements yield yield yield

Only a partial solution: no imperative updates Only a partial solution: no imperative updates

Jed Liu et al. Interruptible Iterators 4

slide-13
SLIDE 13

Imperative Updates

◮ Unsafe to change

underlying data structure directly during iteration

◮ All updates must go

through the iterator

◮ Java: remove()

◮ Previous coroutine

iterators don’t have update

Example: Tree iterator

iterator iterator

Jed Liu et al. Interruptible Iterators 5

slide-14
SLIDE 14

Imperative Updates

◮ Unsafe to change

underlying data structure directly during iteration

◮ All updates must go

through the iterator

◮ Java: remove()

◮ Previous coroutine

iterators don’t have update

Example: Tree iterator

iterator iterator Iterator no longer points to part of the tree

Jed Liu et al. Interruptible Iterators 5

slide-15
SLIDE 15

Interruptible Iterators

JMatch extends coroutine iterators to handle updates via interrupts:

  • 1. Client raises interrupt
  • 2. Iterator handles interrupt
  • 3. Control returns to client after raise

Example Collection c = ...; foreach (Object o = c.elements()) { if (o == null) raise new Remove(); System.out.println(o); }

Jed Liu et al. Interruptible Iterators 6

slide-16
SLIDE 16

Interruptible Iterators

JMatch extends coroutine iterators to handle updates via interrupts:

  • 1. Client raises interrupt
  • 2. Iterator handles interrupt
  • 3. Control returns to client after raise

Example Collection c = ...; foreach (Object o = c.elements()) { if (o == null) raise new Remove(); System.out.println(o); }

Generates a Remove interrupt Generates a Remove interrupt

Jed Liu et al. Interruptible Iterators 6

slide-17
SLIDE 17

Interruptible Iterators

JMatch extends coroutine iterators to handle updates via interrupts:

  • 1. Client raises interrupt
  • 2. Iterator handles interrupt
  • 3. Control returns to client after raise

Example Collection c = ...; foreach (Object o = c.elements()) { if (o == null) raise new Remove(); System.out.println(o); }

Receives and handles the interrupt Receives and handles the interrupt

Jed Liu et al. Interruptible Iterators 6

slide-18
SLIDE 18

Interruptible Iterators

JMatch extends coroutine iterators to handle updates via interrupts:

  • 1. Client raises interrupt
  • 2. Iterator handles interrupt
  • 3. Control returns to client after raise

Example Collection c = ...; foreach (Object o = c.elements()) { if (o == null) raise new Remove(); System.out.println(o); }

Execution continues immediately after raise statement Execution continues immediately after raise statement

Jed Liu et al. Interruptible Iterators 6

slide-19
SLIDE 19

Interruptible Iterators

JMatch extends coroutine iterators to handle updates via interrupts:

  • 1. Client raises interrupt
  • 2. Iterator handles interrupt
  • 3. Control returns to client after raise

Example Collection c = ...; foreach (Object o = c.elements()) { if (o == null) raise new Remove(); System.out.println(o); }

Jed Liu et al. Interruptible Iterators 6

slide-20
SLIDE 20

Declaring Interrupt Handlers

◮ JMatch iterators declare handled interrupts ◮ Compiler checks all interrupts are handled

Example interface Collection { ... Object elements() traps Remove iterates(result); }

Jed Liu et al. Interruptible Iterators 7

slide-21
SLIDE 21

Declaring Interrupt Handlers

◮ JMatch iterators declare handled interrupts ◮ Compiler checks all interrupts are handled

Example interface Collection { ... Object elements() traps Remove iterates(result); }

elements is an iterator that handles Remove interrupts elements is an iterator that handles Remove interrupts

Jed Liu et al. Interruptible Iterators 7

slide-22
SLIDE 22

Writing an Interruptible Iterator

Example: Linked list iterator // Object head; List tail; Object elements() traps SetValue iterates(result) { yield head; foreach (Object elt = tail.elements()) yield elt; }

Jed Liu et al. Interruptible Iterators 8

slide-23
SLIDE 23

Writing an Interruptible Iterator

Example: Linked list iterator // Object head; List tail; Object elements() traps SetValue iterates(result) { yield head; foreach (Object elt = tail.elements()) yield elt; }

Handling SetValue overwrites previous element returned

(` a la Java: ListIterator.set())

Handling SetValue overwrites previous element returned

(` a la Java: ListIterator.set())

Jed Liu et al. Interruptible Iterators 8

slide-24
SLIDE 24

Writing an Interruptible Iterator

Example: Linked list iterator // Object head; List tail; Object elements() traps SetValue iterates(result) { yield head; foreach (Object elt = tail.elements()) yield elt; }

Interrupt appears to be raised by yield; propagates outward like an exception Interrupt appears to be raised by yield; propagates outward like an exception

Jed Liu et al. Interruptible Iterators 8

slide-25
SLIDE 25

Writing an Interruptible Iterator

Example: Linked list iterator // Object head; List tail; Object elements() traps SetValue iterates(result) { try { yield head; } trap (SetValue s) { head = s.value; // resume in caller } foreach (Object elt = tail.elements()) yield elt; }

Jed Liu et al. Interruptible Iterators 8

slide-26
SLIDE 26

Writing an Interruptible Iterator

Example: Linked list iterator // Object head; List tail; Object elements() traps SetValue iterates(result) { try { yield head; } trap (SetValue s) { head = s.value; // resume in caller } foreach (Object elt = tail.elements()) yield elt; }

Interrupt appears here too Interrupt appears here too

Jed Liu et al. Interruptible Iterators 8

slide-27
SLIDE 27

Writing an Interruptible Iterator

Example: Linked list iterator // Object head; List tail; Object elements() traps SetValue iterates(result) { try { yield head; } trap (SetValue s) { head = s.value; // resume in caller } foreach (Object elt = tail.elements()) yield elt; }

Receives interrupt Receives interrupt

Jed Liu et al. Interruptible Iterators 8

slide-28
SLIDE 28

Writing an Interruptible Iterator

Example: Linked list iterator // Object head; List tail; Object elements() traps SetValue iterates(result) { try { yield head; } trap (SetValue s) { head = s.value; // resume in caller } foreach (Object elt = tail.elements()) yield elt; }

Client elements elements elements

yield yield yield

Jed Liu et al. Interruptible Iterators 8

slide-29
SLIDE 29

Writing an Interruptible Iterator

Example: Linked list iterator // Object head; List tail; Object elements() traps SetValue iterates(result) { try { yield head; } trap (SetValue s) { head = s.value; // resume in caller } foreach (Object elt = tail.elements()) yield elt; }

Client elements elements elements

raise raise raise

Jed Liu et al. Interruptible Iterators 8

slide-30
SLIDE 30

Writing an Interruptible Iterator

Example: Linked list iterator // Object head; List tail; Object elements() traps SetValue iterates(result) { try { yield head; } trap (SetValue s) { head = s.value; // resume in caller } foreach (Object elt = tail.elements()) yield elt; }

Client elements elements elements

raise raise raise resume resume resume

Jed Liu et al. Interruptible Iterators 8

slide-31
SLIDE 31

Declarative Iterators

State Machine Iterators Coroutine Iterators Declarative Iterators + Interrupts

Jed Liu et al. Interruptible Iterators 9

slide-32
SLIDE 32

Declarative Iterators

Example: JMatch hash map [PADL 2003] boolean contains(Object key, Object value) iterates(key,value) iterates(key) returns(value) ( int n = hash(key) && Bucket b = table[n] && b.contains(key, value) ) Example uses

Jed Liu et al. Interruptible Iterators 10

slide-33
SLIDE 33

Declarative Iterators

Example: JMatch hash map [PADL 2003] boolean contains(Object key, Object value) iterates(key,value) iterates(key) returns(value) ( int n = hash(key) && Bucket b = table[n] && b.contains(key, value) ) Example uses

Logical formula interpreted in multiple ways Logical formula interpreted in multiple ways

Jed Liu et al. Interruptible Iterators 10

slide-34
SLIDE 34

Declarative Iterators

Example: JMatch hash map [PADL 2003] boolean contains(Object key, Object value) iterates(key,value) iterates(key) returns(value) ( int n = hash(key) && Bucket b = table[n] && b.contains(key, value) ) Example uses

Mode declarations Mode declarations

Jed Liu et al. Interruptible Iterators 10

slide-35
SLIDE 35

Declarative Iterators

Example: JMatch hash map [PADL 2003] boolean contains(Object key, Object value) iterates(key,value) iterates(key) returns(value) ( int n = hash(key) && Bucket b = table[n] && b.contains(key, value) ) Example uses foreach (map.contains(Object key, Object value)) ...

Iterates all key-value pairs Iterates all key-value pairs

Jed Liu et al. Interruptible Iterators 10

slide-36
SLIDE 36

Declarative Iterators

Example: JMatch hash map [PADL 2003] boolean contains(Object key, Object value) iterates(key,value) iterates(key) returns(value) ( int n = hash(key) && Bucket b = table[n] && b.contains(key, value) ) Example uses foreach (map.contains(Object key, Object value)) ... foreach (map.contains(Object key, "foo")) ...

Iterates all keys that map to a given value Iterates all keys that map to a given value

Jed Liu et al. Interruptible Iterators 10

slide-37
SLIDE 37

Declarative Iterators

Example: JMatch hash map [PADL 2003] boolean contains(Object key, Object value) iterates(key,value) iterates(key) returns(value) ( int n = hash(key) && Bucket b = table[n] && b.contains(key, value) ) Example uses foreach (map.contains(Object key, Object value)) ... foreach (map.contains(Object key, "foo")) ... let map.contains("foo", Object value);

Returns value mapped by a given key Returns value mapped by a given key

Jed Liu et al. Interruptible Iterators 10

slide-38
SLIDE 38

Declarative Iterators

Example: JMatch hash map [PADL 2003] boolean contains(Object key, Object value) iterates(key,value) iterates(key) returns(value) ( int n = hash(key) && Bucket b = table[n] && b.contains(key, value) ) Example uses foreach (map.contains(Object key, Object value)) ... foreach (map.contains(Object key, "foo")) ... let map.contains("foo", Object value); if (map.contains("foo", "bar")) ...

Implicit mode Implicit mode

Jed Liu et al. Interruptible Iterators 10

slide-39
SLIDE 39

Declarative Iterators + Imperative Update

Example: JMatch hash map [PADL 2003] boolean contains(Object key, Object value) traps Remove iterates(key,value) iterates(key) returns(value) ( int n = hash(key) && Bucket b = table[n] && b.contains(key, value) ) Example use foreach (map.contains(Object key, Object value)) if (value == null) raise new Remove();

Updates can be supported via interrupts Updates can be supported via interrupts

Jed Liu et al. Interruptible Iterators 10

slide-40
SLIDE 40

Implementation

◮ JMatch implemented using Polyglot extensible

compiler framework [CC 2003]

◮ Java back-end available for download ◮ Designed C++ back-end for performance evaluation ◮ Better memory management for coroutine stack

◮ Tail-yield optimisation: send values back to

client in constant time

Client elements elements elements

yield

Jed Liu et al. Interruptible Iterators 11

slide-41
SLIDE 41

Evaluation

Expressiveness (LOC) Java JMatch Savings ArrayList 204 112 45% LinkedList 249 155 38% HashMap 434 158 64% TreeMap 805 472 41% Total 1692 897 47% Performance vs. C++ STL Average 3% difference iterating 250k elements: LinkedList, HashMap, TreeMap vs. STL equivalent

◮ More results in paper, including vs. Java

Jed Liu et al. Interruptible Iterators 12

slide-42
SLIDE 42

Related Work

◮ Coroutine iterators

◮ CLU, ICON, Python, Ruby, C# ◮ Sather: Limited support for imperative updates

through “hot” arguments

◮ Coroutines

◮ Simula, Modula-2, BETA

◮ Resumption-style exceptions

◮ Cedar

◮ First-class continuations

◮ SML/NJ, Scheme, Ruby Jed Liu et al. Interruptible Iterators 13

slide-43
SLIDE 43

Summary

◮ Interrupts make it easier to write iteration abstractions

with imperative update

◮ Supports coroutine and declarative iterators

◮ Implemented for Java in JMatch ◮ LOC savings without performance penalty

Also in the paper...

◮ Non-compositionality of Java iterators ◮ Interaction of interrupts & exceptions ◮ Static checking of interrupts

◮ Checks all raised interrupts have unique handler

◮ Support for first-class iterator objects

◮ Implement Java iterator interface

http://www.cs.cornell.edu/projects/jmatch/

Jed Liu et al. Interruptible Iterators 14

slide-44
SLIDE 44

Java Iterators are Non-Compositional

interface Iterator { boolean hasNext(); Object next(); void remove(); }

Client 1 2 3 4 5

Jed Liu et al. Interruptible Iterators 15

slide-45
SLIDE 45

Java Iterators are Non-Compositional

interface Iterator { boolean hasNext(); Object next(); void remove(); }

Client List iterator 1 2 3 4 5

Jed Liu et al. Interruptible Iterators 15

slide-46
SLIDE 46

Java Iterators are Non-Compositional

interface Iterator { boolean hasNext(); Object next(); void remove(); }

Client Filtering iterator List iterator 1 2 3 4 5

Jed Liu et al. Interruptible Iterators 15

slide-47
SLIDE 47

Java Iterators are Non-Compositional

interface Iterator { boolean hasNext(); Object next(); void remove(); }

Client next() next() Filtering iterator List iterator 1 2 3 4 5

Jed Liu et al. Interruptible Iterators 15

slide-48
SLIDE 48

Java Iterators are Non-Compositional

interface Iterator { boolean hasNext(); Object next(); void remove(); }

Client hasNext() hasNext() Filtering iterator List iterator 1 2 3 4 5

Jed Liu et al. Interruptible Iterators 15

slide-49
SLIDE 49

Java Iterators are Non-Compositional

interface Iterator { boolean hasNext(); Object next(); void remove(); }

Client remove() remove()

!

Filtering iterator List iterator 1 2 3 4 5

Jed Liu et al. Interruptible Iterators 15

slide-50
SLIDE 50

Performance Results

ArrayList LinkedList HashMap TreeMap JMatch 135.0 56.1 3.7 3.1 C++ STL 215.0 57.7 3.1 3.9 Java 6.3 10.3 4.2 3.5

Millions of elements iterated per second, iterating over collections

  • f 250k elements. Average of 8 measurements, σ ≤ 5%.

Jed Liu et al. Interruptible Iterators 16