Ring ADT.
- Provides analogous functionality to a doubly-linked list
implementation.
- Completely symmetric set of operations.
- Operations on the ADT do not lead to results that are
outside the domain of the ADT (closed interface).
- Alternative to container/list.
R=rsc
DELTA=489 (489 added, 0 deleted, 0 changed)
OCL=32284
CL=32323
diff --git a/src/pkg/container/ring/ring.go b/src/pkg/container/ring/ring.go
new file mode 100644
index 0000000..62dba6f
--- /dev/null
+++ b/src/pkg/container/ring/ring.go
@@ -0,0 +1,174 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The ring package implements operations on circular lists.
+package ring
+
+// A Ring is an element of a circular list, or ring.
+// Rings do not have a beginning or end; a pointer to any ring element
+// serves as reference to the entire ring. Empty rings are represented
+// as nil Ring pointers. The zero value for a Ring is a one-element
+// ring with a nil Value.
+//
+type Ring struct {
+ next, prev *Ring;
+ Value interface{}; // for use by client; untouched by this library
+}
+
+
+func (r *Ring) init() *Ring {
+ r.next = r;
+ r.prev = r;
+ return r;
+}
+
+
+// Next returns the next ring element. r must not be empty.
+func (r *Ring) Next() *Ring {
+ if r.next == nil {
+ return r.init();
+ }
+ return r.next;
+}
+
+
+// Prev returns the previous ring element. r must not be empty.
+func (r *Ring) Prev() *Ring {
+ if r.next == nil {
+ return r.init();
+ }
+ return r.prev;
+}
+
+
+// Move moves n % r.Len() elements backward (n < 0) or forward (n > 0)
+// in the ring and returns that ring element. r must not be empty.
+//
+func (r *Ring) Move(n int) *Ring {
+ if r.next == nil {
+ return r.init();
+ }
+ switch {
+ case n < 0:
+ for ; n < 0; n++ {
+ r = r.prev;
+ }
+ case n > 0:
+ for ; n > 0; n-- {
+ r = r.next;
+ }
+ }
+ return r;
+}
+
+
+// New creates a ring of n elements.
+func New(n int) *Ring {
+ if n <= 0 {
+ return nil;
+ }
+ r := new(Ring);
+ p := r;
+ for i := 1; i < n; i++ {
+ p.next = &Ring{prev: p};
+ p = p.next;
+ }
+ p.next = r;
+ r.prev = p;
+ return r;
+}
+
+
+// Link connects ring r with with ring s such that r.Next(1)
+// becomes s and returns the original value for r.Next(1).
+// r must not be empty.
+//
+// If r and s point to the same ring, linking
+// them removes the elements between r and s from the ring.
+// The removed elements form a subring and the result is a
+// reference to that subring (if no elements were removed,
+// the result is still the original value for r.Next(1),
+// and not nil).
+//
+// If r and s point to different rings, linking
+// them creates a single ring with the elements of s inserted
+// after r. The result points to the element following the
+// last element of s after insertion.
+//
+func (r *Ring) Link(s *Ring) *Ring {
+ n := r.Next();
+ if s != nil {
+ p := s.Prev();
+ // Note: Cannot use multiple assignment because
+ // evaluation order of LHS is not specified.
+ r.next = s;
+ s.prev = r;
+ n.prev = p;
+ p.next = n;
+ }
+ return n;
+}
+
+
+// Unlink removes n % r.Len() elements from the ring r, starting
+// at r.Next(). If n % r.Len() == 0, r remains unchanged.
+// The result is the removed subring. r must not be empty.
+//
+func (r *Ring) Unlink(n int) *Ring {
+ if n <= 0 {
+ return nil;
+ }
+ return r.Link(r.Move(n + 1));
+}
+
+
+// Len computes the number of elements in ring r.
+// It executes in time proportional to the number of elements.
+//
+func (r *Ring) Len() int {
+ n := 0;
+ if r != nil {
+ n = 1;
+ for p := r.Next(); p != r; p = p.next {
+ n++;
+ }
+ }
+ return n;
+}
+
+
+// Forward returns a channel for forward iteration through a ring.
+// Iteration is undefined if the ring is changed during iteration.
+//
+func (r *Ring) Forward() <-chan *Ring {
+ c := make(chan *Ring);
+ go func() {
+ if r != nil {
+ c <- r;
+ for p := r.Next(); p != r; p = p.next {
+ c <- p;
+ }
+ }
+ close(c);
+ }();
+ return c;
+}
+
+
+// Backward returns a channel for backward iteration through a ring.
+// Iteration is undefined if the ring is changed during iteration.
+//
+func (r *Ring) Backward() <-chan *Ring {
+ c := make(chan *Ring);
+ go func() {
+ if r != nil {
+ c <- r;
+ for p := r.Prev(); p != r; p = p.prev {
+ c <- p;
+ }
+ }
+ close(c);
+ }();
+ return c;
+}