eece 310: software engineering iteration abstraction

40
EECE 310: Software Engineering Iteration Abstraction

Upload: miles-miles

Post on 01-Jan-2016

231 views

Category:

Documents


2 download

TRANSCRIPT

EECE 310: Software Engineering

Iteration Abstraction

Learning Objectives

• Define the basic elements used in iterators• Use iterators to iterate over a collection• Implement iterators and the associated

generator classes for an ADT• Understand the design issues for iterators• Design iterators that support concurrency

Problem

• Consider the IntSet ADT introduced earlier• Let’s say you want to compute the sum of

elements in the set. How would you do it ?– Add a member function computeSum– Copy the rep to another array and return it– Add an indexing operation to the ADT– Add a new iterator abstraction

• Which method would you choose and why ?

Iteration Abstraction

• General way to iterate over the elements of an ADT without tying the iteration to a specific operation (e.g., summation)– Efficient in space and time (as far as possible)

For each element e of the ADT: Perform operation o on e

Implementation

• Implemented using two entities:

1. Generator: Keeps track of the state of the iteration and exposes operations to actually perform the iteration

2. Iterator: Operation of an ADT that returns a generator object to begin the iteration process

Iteration Abstraction: Generators

ADT

state 2

Client Code 1

Client Code 2

state 1

Generator objects

Client Code 3

Generators : Keeping track of State

• Objects that keep track of the state of the iteration in its rep– Implements the Iterator interface in Java– Consists of methods hasNext and next– next method throws NoSuchElementException

• Multiple generators can operate on an ADT

• Generators can be passed around to procedures

Generators: Examplepublic interface Iterator<T> {

public boolean hasNext()// EFFECTS: Returns true if there are more elements

to// yield, else returns false

public T next( ) throws NoSuchElementException// MODIFIES: this// EFFECTS: If there are more results to yield,// returns the next result and records the state of

this// Otherwise, throws NoSuchElementException

Iterator: Produces a generator

• Operation of an ADT or a stand-alone procedure that returns a generator object– Different iterators can produce different generators

(e.g., forward and reverse iterator)– Multiple calls to the iterator can produce different

generators (for local iteration)

• The specification of the iterator defines the behavior of the generator object it returns – add a requires clause at the end constraining its use

Iterator: IntSet Example

public class IntSet {... public Iterator<Integer> elements ( ) // EFFECTS: returns a generator that will produce // all the elements of this, each exactly once, // in arbitrary order. // REQUIRES: this must not be modified while // the generator is in use.}

Learning Objectives

• Define the basic elements used in iterators

• Use iterators to iterate over a collection

• Implement iterators and the associated generator classes for an ADT

• Design iterators that support concurrency

How do we use iterators ?

ADT (e.g., IntSet)

Has iterator methods that

return generator objects, e.g.,

elements

Generator object:

implements the Java iterator interface):1.hasNext

2.next

Step 1: Client invokes the iterator operation on ADT and stores the returned generator object

IntSet s = new IntSet(v);….Iterator g = s.elements();

Step 2: Perform the iteration using the hasNext and next methods of the generator object

while ( g.hasNext() ) { Integer o = g.next( );

int i = o.intValue();}

Optional Step: May pass the generator object to different procedures for doing the operation

e.g., int m = computeMax(g);

Example: Using Iteratorspublic static int max(Iterator<Integer> g) throws EmptyException{ // REQUIRES: g!=null && g contains only Integers // MODIFIES: g // EFFECTS: Throws EmptyException if no elements in g, otherwise return // the maximum element of the collection try{

int m = ( g.next() ).intValue() ; while ( g.hasNext() ) {

int x = ( g.next() ).intValue(); if (m < x) m = x;

} return m;

} catch( NoSuchElementException e) {

throw new EmptyException(“Comp.max”); }}

Some points on using Generators• Using code interacts with a generator via the iterator

interface (defined in java.util package)

• Using code must obey the constraint imposed on it by the iterator’s requires clause (given after the EFFECTS clause)

• Generators can be passed as arguments and returned as results by procedures

• Generators may be primed before using them in loops

• Generators may loop infinitely, e.g., list of prime numbers

In-class Exercise

• Write a procedure that iterates over the elements of the IntSet ADT and prints all Integers that exceed a certain threshold, max

How would you do this if you had an iterator that allowed you to choose elements that fall within a certain range, say, min and max.

Learning Objectives

• Define the basic elements used in iterators• Use iterators to iterate over a collection• Implement iterators and the associated

generator classes for an ADT• Understand the design issues for iterators• Design iterators that support concurrency

Implementing Iteratorspublic class IntSet { private vector<Integer> els; // The rep...

public Iterator<Integer> elements ( ) // EFFECTS: returns a generator object that will // produce all the elements of this, each exactly

// once, in arbitrary oder. // REQUIRES: this must not be modified while // the generator is in use.

return new IntSetGen(this);}

Implementing generators

• All generators implement Java’s iterator interface– Using code interacts with it through the interface– You must implement the methods hasNext and next

• Generator has access to the rep of the ADT– Must not be exposed to the using code

• Generator has its own rep to store the state of the iteration which also should not be exposed

IntSetGen: Scope

• IntSetGen is declared as a nested class within the IntSet ADT and it’s scope is private– Clients cannot create IntSetGen objects except

through the iterator method of the IntSet ADT– Clients cannot directly access any operation of

IntSetGen except through the iterator interface– IntSetGen has undeterred access to the private

methods of the IntSet including its rep

IntSetGen: Declarationpublic class IntSet { private vector<Integer> els; // The rep public Iterator<Integer> elements( ) { // Iterator // EFFECTS: … return new IntSetGen( this ); }

private static class IntSetGen implements Iterator<Integer>

{ // Generator object returned by elements }

IntSetGen: Rep and Constructorprivate static class IntSetGen implements Iterator<Integer>{

private int index;private IntSet s;

// ConstructorIntSetGen(IntSet is) {

// REQUIRES: is!= null // EFFECTS: Initializes the generator for a

// new iteration cycle s = is; index = 0;

}

Passed in by the elements() method of the IntSet ADT

IntSetGen: hasNext operation

public boolean hasNext( ){ // EFFECTS: If not reached the end // the elements vector, return true // otherwise, return false

if ( index == s.els.size( ) )return false;

elsereturn true;

}

IntSet ADT’sRep – can access this because it is declared as a nested class

IntSetGen: next operation

public Integer next( ) throws NoSuchElementException { // EFFECTS: If there is a next object, return it // Otherwise, throw the NoSuchElementException

if ( hasNext( ) )return s.els.get(index++);

else throw new

NoSuchElementException(“IntSet.elements”);}

Use the name of the iterator method that produced the generator object

In-class exercise

• Implement an Iterator for the IntSet ADT, to return all integers of the IntSet that satisfy a given critereon. The iterator takes as its argument a type Check with a public method:

public boolean checker(Integer) - that returns true if and only if the Integer satisfies the criteria

Assume that the Check class is given to you. Also, write the implementation of its associated generator object.

Learning Objectives

• Define the basic elements used in iterators• Use iterators to iterate over a collection• Implement iterators and the associated

generator classes for an ADT• Understand the design issues for iterators• Design iterators that support concurrency

Design Issues: Multiple Iterators

• Types may sometimes have multiple iterators

• Examples:– ForwardIterators, ReverseIterators for ordered

collections such as lists– Iterators that return elements satisfying a certain

critereon (say, within a specified range)– Iterators that perform some operation on their

elements prior to returning them (e.g., sorting)

Design Issues: Changes during Iteration

• Default behavior so far: Disallow changes during iteration (specified in post-REQUIRES clause)

• If changes are allowed, what are its semantics ?– State of iteration is what it was when the generator

was created (requires creating copy)– Iteration sequence changes when changes occur to

ADT (difficult to ensure consistency of state)• How do we reset iterator to go back in the collection ?• What if the current element is removed in a list ?

Design Issues: Can the generator itself change the ADT ?

• The generator can change the rep of the ADT as long as it does not change the abstraction– Example: An iterator that returns the elements of an

un-ordered collection such as set in sorted order may sort the collection during the process of iteration

• Iterator changes the abstraction exposed by ADT– This is usually best avoided unless there is a

compelling need. For example, iterating over a task list may itself spawn new tasks to be added to the list.

Testing Iterators

• Iterators are tested like procedures, except that they have paths in their specifications that are similar to loops in procedures– Should test for returning generators that produce

0, 1, 2 results/elements

• Generators are tested like any other ADT(Boundary conditions, aliasing etc.)

Learning Objectives

• Define the basic elements used in iterators• Use iterators to iterate over a collection• Implement iterators and the associated

generator classes for an ADT• Understand the design issues for iterators• Design iterators that support concurrency

Concurrent Iterators: Read only

• Assume that we want to iterate over a list in two separate threads, but without modifying it. Is this allowed ?– Yes, as long as we keep the generator objects

separate. i.e., we do not share generators– Each generator keeps track of where it is in the

iteration – no changes to the state of the ADT– We need to make the iterator method

synchronized (why ?)

Concurrent Iterators: Read-Write

Thread 1

Iterator<Integer> g = is.elements();

while ( g.hasNext() ) {Integer i = g.next();System.out.println(i + “ “);

}

Thread 2

is.add(1);is.add(2);is.add(3);is.add(4);is.remove(2);

No guarantees about what iterator returns

How to solve the concurrent iterator problem ?

• Disallow concurrent writes by requiring clients to take a lock before the iteration operation– Also disallows concurrent reads – performance !– Need to explicitly release lock when done

• Make a copy of the collection before iteration

• Throw a concurrent modification exception

Making a copy

• Create a copy of the list when you call the iterator method, and perform iteration over it– Need to ensure that copy operation is performed

in the iterator method in synchronized mode– Can be expensive to copy large lists in memory– Need to perform deep copy of elements to

disallow any modifications– Iterator may operate on stale version of collection

Concurrent modification exception

• Exception thrown when the ADT is modified concurrently with the iteration– Thrown to the thread that performs the iteration– Up to the thread what it wants to do with it– Only one exception per concurrent modification

will be thrown

• ConcurrentModification is a checked exception

CME: Usage public ... search (List list) { try { ListIterator iterator = list.listIterator(); while(iterator.hasNext()) { Object o = iterator.next(); //do something ... } } catch (ConcurrentModificationException concEx) { //handle this case, maybe just iterate the collection again return search(list); } }

CME: Implementation - 102 * The number of times this list has been structurally modified.03 * Structural modifications are those that change the size of the04 * list, or otherwise perturb it in such a fashion that iterations in05 * progress may yield incorrect results.…..15 * Use of this field by subclasses is optional. If a subclass16 * wishes to provide fail-fast iterators (and list iterators), then it17 * merely has to increment this field in its add(int, Object) and18 * remove(int) methods (and any other methods that it overrides19 * that result in structural modifications to the list). A single call to20 * add(int, Object) or remove(int) must add no more than21 * one to this field, or the iterators (and list iterators) will throw22 * bogus ConcurrentModificationExceptions. If an implementation23 * does not wish to provide fail-fast iterators, this field may be24 * ignored.25 */26 protected transient int modCount = 0;

CME: Implementation - 230 private class Itr implements Iterator<E> {31 int expectedModCount = modCount;32 33 public boolean hasNext() {34 // implementation omitted 35 }36 37 public E next() {38 checkForComodification();39 // implementation omitted 40 41 }42 43 private void checkForComodification() {44 if (modCount != expectedModCount)45 throw new ConcurrentModificationException();46 }47 }

Class Exercise

• Add a concurrent iterator to the IntSet ADT that throws a ConcurrentModificationException when another thread attempts to modify/remove from the set during the iteration.

Learning Objectives

• Define the basic elements used in iterators

• Use iterators to iterate over a collection

• Implement iterators and the associated generator classes for an ADT

• Design iterators that support concurrency