blob: 6d3b3e5b322266bd5bebc90f949c564947ff9fa8 [file] [log] [blame]
Robert Griesemer6d3d25d2009-07-28 14:54:49 -07001// Copyright 2009 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
Nigel Tao6a186d32011-04-20 09:57:05 +10005// Package ring implements operations on circular lists.
Robert Griesemer6d3d25d2009-07-28 14:54:49 -07006package ring
7
8// A Ring is an element of a circular list, or ring.
9// Rings do not have a beginning or end; a pointer to any ring element
10// serves as reference to the entire ring. Empty rings are represented
11// as nil Ring pointers. The zero value for a Ring is a one-element
12// ring with a nil Value.
13//
14type Ring struct {
Robert Griesemer5a1d3322009-12-15 15:33:31 -080015 next, prev *Ring
16 Value interface{} // for use by client; untouched by this library
Robert Griesemer6d3d25d2009-07-28 14:54:49 -070017}
18
Robert Griesemer6d3d25d2009-07-28 14:54:49 -070019func (r *Ring) init() *Ring {
Robert Griesemer5a1d3322009-12-15 15:33:31 -080020 r.next = r
21 r.prev = r
22 return r
Robert Griesemer6d3d25d2009-07-28 14:54:49 -070023}
24
Robert Griesemer6d3d25d2009-07-28 14:54:49 -070025// Next returns the next ring element. r must not be empty.
26func (r *Ring) Next() *Ring {
27 if r.next == nil {
Robert Griesemer40621d52009-11-09 12:07:39 -080028 return r.init()
Robert Griesemer6d3d25d2009-07-28 14:54:49 -070029 }
Robert Griesemer5a1d3322009-12-15 15:33:31 -080030 return r.next
Robert Griesemer6d3d25d2009-07-28 14:54:49 -070031}
32
Robert Griesemer6d3d25d2009-07-28 14:54:49 -070033// Prev returns the previous ring element. r must not be empty.
34func (r *Ring) Prev() *Ring {
35 if r.next == nil {
Robert Griesemer40621d52009-11-09 12:07:39 -080036 return r.init()
Robert Griesemer6d3d25d2009-07-28 14:54:49 -070037 }
Robert Griesemer5a1d3322009-12-15 15:33:31 -080038 return r.prev
Robert Griesemer6d3d25d2009-07-28 14:54:49 -070039}
40
Robert Griesemerd27bae52009-07-28 15:03:05 -070041// Move moves n % r.Len() elements backward (n < 0) or forward (n >= 0)
Robert Griesemer6d3d25d2009-07-28 14:54:49 -070042// in the ring and returns that ring element. r must not be empty.
43//
44func (r *Ring) Move(n int) *Ring {
45 if r.next == nil {
Robert Griesemer40621d52009-11-09 12:07:39 -080046 return r.init()
Robert Griesemer6d3d25d2009-07-28 14:54:49 -070047 }
48 switch {
49 case n < 0:
50 for ; n < 0; n++ {
Robert Griesemer40621d52009-11-09 12:07:39 -080051 r = r.prev
Robert Griesemer6d3d25d2009-07-28 14:54:49 -070052 }
53 case n > 0:
54 for ; n > 0; n-- {
Robert Griesemer40621d52009-11-09 12:07:39 -080055 r = r.next
Robert Griesemer6d3d25d2009-07-28 14:54:49 -070056 }
57 }
Robert Griesemer5a1d3322009-12-15 15:33:31 -080058 return r
Robert Griesemer6d3d25d2009-07-28 14:54:49 -070059}
60
Robert Griesemer6d3d25d2009-07-28 14:54:49 -070061// New creates a ring of n elements.
62func New(n int) *Ring {
63 if n <= 0 {
Robert Griesemer40621d52009-11-09 12:07:39 -080064 return nil
Robert Griesemer6d3d25d2009-07-28 14:54:49 -070065 }
Robert Griesemer5a1d3322009-12-15 15:33:31 -080066 r := new(Ring)
67 p := r
Robert Griesemer6d3d25d2009-07-28 14:54:49 -070068 for i := 1; i < n; i++ {
Robert Griesemer5a1d3322009-12-15 15:33:31 -080069 p.next = &Ring{prev: p}
70 p = p.next
Robert Griesemer6d3d25d2009-07-28 14:54:49 -070071 }
Robert Griesemer5a1d3322009-12-15 15:33:31 -080072 p.next = r
73 r.prev = p
74 return r
Robert Griesemer6d3d25d2009-07-28 14:54:49 -070075}
76
Shenghou Ma42c89042012-11-22 02:58:24 +080077// Link connects ring r with ring s such that r.Next()
Robert Griesemerd27bae52009-07-28 15:03:05 -070078// becomes s and returns the original value for r.Next().
Robert Griesemer6d3d25d2009-07-28 14:54:49 -070079// r must not be empty.
80//
81// If r and s point to the same ring, linking
82// them removes the elements between r and s from the ring.
83// The removed elements form a subring and the result is a
84// reference to that subring (if no elements were removed,
Robert Griesemerd27bae52009-07-28 15:03:05 -070085// the result is still the original value for r.Next(),
Robert Griesemer6d3d25d2009-07-28 14:54:49 -070086// and not nil).
87//
88// If r and s point to different rings, linking
89// them creates a single ring with the elements of s inserted
90// after r. The result points to the element following the
91// last element of s after insertion.
92//
93func (r *Ring) Link(s *Ring) *Ring {
Robert Griesemer5a1d3322009-12-15 15:33:31 -080094 n := r.Next()
Robert Griesemer6d3d25d2009-07-28 14:54:49 -070095 if s != nil {
Robert Griesemer5a1d3322009-12-15 15:33:31 -080096 p := s.Prev()
Robert Griesemer6d3d25d2009-07-28 14:54:49 -070097 // Note: Cannot use multiple assignment because
98 // evaluation order of LHS is not specified.
Robert Griesemer5a1d3322009-12-15 15:33:31 -080099 r.next = s
100 s.prev = r
101 n.prev = p
102 p.next = n
Robert Griesemer6d3d25d2009-07-28 14:54:49 -0700103 }
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800104 return n
Robert Griesemer6d3d25d2009-07-28 14:54:49 -0700105}
106
Robert Griesemer6d3d25d2009-07-28 14:54:49 -0700107// Unlink removes n % r.Len() elements from the ring r, starting
108// at r.Next(). If n % r.Len() == 0, r remains unchanged.
109// The result is the removed subring. r must not be empty.
110//
111func (r *Ring) Unlink(n int) *Ring {
112 if n <= 0 {
Robert Griesemer40621d52009-11-09 12:07:39 -0800113 return nil
Robert Griesemer6d3d25d2009-07-28 14:54:49 -0700114 }
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800115 return r.Link(r.Move(n + 1))
Robert Griesemer6d3d25d2009-07-28 14:54:49 -0700116}
117
Robert Griesemer6d3d25d2009-07-28 14:54:49 -0700118// Len computes the number of elements in ring r.
119// It executes in time proportional to the number of elements.
120//
121func (r *Ring) Len() int {
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800122 n := 0
Robert Griesemer6d3d25d2009-07-28 14:54:49 -0700123 if r != nil {
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800124 n = 1
Robert Griesemer6d3d25d2009-07-28 14:54:49 -0700125 for p := r.Next(); p != r; p = p.next {
Robert Griesemer40621d52009-11-09 12:07:39 -0800126 n++
Robert Griesemer6d3d25d2009-07-28 14:54:49 -0700127 }
128 }
Robert Griesemer5a1d3322009-12-15 15:33:31 -0800129 return n
Robert Griesemer6d3d25d2009-07-28 14:54:49 -0700130}
131
Kyle Consalus3629d722011-02-08 20:07:05 -0800132// Do calls function f on each element of the ring, in forward order.
133// The behavior of Do is undefined if f changes *r.
134func (r *Ring) Do(f func(interface{})) {
135 if r != nil {
136 f(r.Value)
137 for p := r.Next(); p != r; p = p.next {
138 f(p.Value)
Robert Griesemer6d3d25d2009-07-28 14:54:49 -0700139 }
Kyle Consalus3629d722011-02-08 20:07:05 -0800140 }
Robert Griesemer6d3d25d2009-07-28 14:54:49 -0700141}