xmpp/status.go
author Chris Jones <chris@cjones.org>
Sun, 29 Sep 2013 21:55:08 -0600
changeset 160 ba2428230f71
parent 155 fdd637733628
child 163 3f891f7fe817
permissions -rw-r--r--
to-do update.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
153
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
     1
// Track the current status of the connection to the server.
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
     2
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
     3
package xmpp
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
     4
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
     5
import (
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
     6
	"fmt"
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
     7
)
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
     8
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
     9
type statmgr struct {
155
Chris Jones <christian.jones@sri.com>
parents: 153
diff changeset
    10
	newStatus   chan Status
153
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    11
	newlistener chan chan Status
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    12
}
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    13
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    14
func newStatmgr(client chan<- Status) *statmgr {
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    15
	s := statmgr{}
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    16
	s.newStatus = make(chan Status)
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    17
	s.newlistener = make(chan chan Status)
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    18
	go s.manager(client)
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    19
	return &s
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    20
}
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    21
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    22
func (s *statmgr) manager(client chan<- Status) {
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    23
	// We handle this specially, in case the client doesn't read
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    24
	// our final status message.
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    25
	defer func() {
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    26
		if client != nil {
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    27
			select {
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    28
			case client <- StatusShutdown:
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    29
			default:
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    30
			}
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    31
			close(client)
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    32
		}
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    33
	}()
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    34
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    35
	stat := StatusUnconnected
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    36
	listeners := []chan Status{}
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    37
	for {
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    38
		select {
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    39
		case stat = <-s.newStatus:
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    40
			for _, l := range listeners {
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    41
				sendToListener(l, stat)
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    42
			}
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    43
			if client != nil && stat != StatusShutdown {
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    44
				client <- stat
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    45
			}
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    46
		case l, ok := <-s.newlistener:
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    47
			if !ok {
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    48
				return
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    49
			}
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    50
			defer close(l)
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    51
			sendToListener(l, stat)
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    52
			listeners = append(listeners, l)
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    53
		}
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    54
	}
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    55
}
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    56
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    57
func sendToListener(listen chan Status, stat Status) {
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    58
	for {
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    59
		select {
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    60
		case <-listen:
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    61
		case listen <- stat:
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    62
			return
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    63
		}
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    64
	}
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    65
}
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    66
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    67
func (cl *Client) setStatus(stat Status) {
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    68
	cl.statmgr.setStatus(stat)
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    69
}
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    70
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    71
func (s *statmgr) setStatus(stat Status) {
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    72
	s.newStatus <- stat
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    73
}
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    74
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    75
func (s *statmgr) newListener() <-chan Status {
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    76
	l := make(chan Status, 1)
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    77
	s.newlistener <- l
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    78
	return l
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    79
}
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    80
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    81
func (s *statmgr) close() {
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    82
	close(s.newlistener)
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    83
}
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    84
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    85
func (s *statmgr) awaitStatus(waitFor Status) error {
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    86
	// BUG(chris): This routine leaks one channel each time it's
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    87
	// called. Listeners are never removed.
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    88
	l := s.newListener()
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    89
	for current := range l {
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    90
		if current == waitFor {
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    91
			return nil
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    92
		}
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    93
		if current == StatusShutdown {
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    94
			break
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    95
		}
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    96
		if current > waitFor {
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    97
			return nil
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    98
		}
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
    99
	}
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   100
	return fmt.Errorf("shut down waiting for status change")
bbd4166df95d Simplified the API: There's only one constructor, and it does everything necessary to initiate the stream. StartSession() and Roster.Update() have both been eliminated.
Chris Jones <christian.jones@sri.com>
parents:
diff changeset
   101
}