github.com/zhongdalu/gf@v1.0.0/g/container/gring/gring.go (about)

     1  // Copyright 2018 gf Author(https://github.com/zhongdalu/gf). All Rights Reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the MIT License.
     4  // If a copy of the MIT was not distributed with this file,
     5  // You can obtain one at https://github.com/zhongdalu/gf.
     6  
     7  // Package gring provides a concurrent-safe/unsafe ring(circular lists).
     8  package gring
     9  
    10  import (
    11  	"container/ring"
    12  	"github.com/zhongdalu/gf/g/container/gtype"
    13  	"github.com/zhongdalu/gf/g/internal/rwmutex"
    14  )
    15  
    16  type Ring struct {
    17  	mu    *rwmutex.RWMutex
    18  	ring  *ring.Ring  // Underlying ring.
    19  	len   *gtype.Int  // Length(already used size).
    20  	cap   *gtype.Int  // Capability(>=len).
    21  	dirty *gtype.Bool // Dirty, which means the len and cap should be recalculated.
    22  	// It's marked dirty when the size of ring changes.
    23  }
    24  
    25  func New(cap int, unsafe ...bool) *Ring {
    26  	return &Ring{
    27  		mu:    rwmutex.New(unsafe...),
    28  		ring:  ring.New(cap),
    29  		len:   gtype.NewInt(),
    30  		cap:   gtype.NewInt(cap),
    31  		dirty: gtype.NewBool(),
    32  	}
    33  }
    34  
    35  // Val returns the item's value of current position.
    36  func (r *Ring) Val() interface{} {
    37  	r.mu.RLock()
    38  	v := r.ring.Value
    39  	r.mu.RUnlock()
    40  	return v
    41  }
    42  
    43  // Len returns the size of ring.
    44  func (r *Ring) Len() int {
    45  	r.checkAndUpdateLenAndCap()
    46  	return r.len.Val()
    47  }
    48  
    49  // Cap returns the capacity of ring.
    50  func (r *Ring) Cap() int {
    51  	r.checkAndUpdateLenAndCap()
    52  	return r.cap.Val()
    53  }
    54  
    55  // Checks and updates the len and cap of ring when ring is dirty.
    56  func (r *Ring) checkAndUpdateLenAndCap() {
    57  	if !r.dirty.Val() {
    58  		return
    59  	}
    60  	totalLen := 0
    61  	emptyLen := 0
    62  	if r.ring != nil {
    63  		r.mu.RLock()
    64  		for p := r.ring.Next(); p != r.ring; p = p.Next() {
    65  			if p.Value == nil {
    66  				emptyLen++
    67  			}
    68  			totalLen++
    69  		}
    70  		r.mu.RUnlock()
    71  	}
    72  	r.cap.Set(totalLen)
    73  	r.len.Set(totalLen - emptyLen)
    74  	r.dirty.Set(false)
    75  }
    76  
    77  // Set sets value to the item of current position.
    78  func (r *Ring) Set(value interface{}) *Ring {
    79  	r.mu.Lock()
    80  	if r.ring.Value == nil {
    81  		r.len.Add(1)
    82  	}
    83  	r.ring.Value = value
    84  	r.mu.Unlock()
    85  	return r
    86  }
    87  
    88  // Put sets <value> to current item of ring and moves position to next item.
    89  func (r *Ring) Put(value interface{}) *Ring {
    90  	r.mu.Lock()
    91  	if r.ring.Value == nil {
    92  		r.len.Add(1)
    93  	}
    94  	r.ring.Value = value
    95  	r.ring = r.ring.Next()
    96  	r.mu.Unlock()
    97  	return r
    98  }
    99  
   100  // Move moves n % r.Len() elements backward (n < 0) or forward (n >= 0)
   101  // in the ring and returns that ring element. r must not be empty.
   102  func (r *Ring) Move(n int) *Ring {
   103  	r.mu.Lock()
   104  	r.ring = r.ring.Move(n)
   105  	r.mu.Unlock()
   106  	return r
   107  }
   108  
   109  // Prev returns the previous ring element. r must not be empty.
   110  func (r *Ring) Prev() *Ring {
   111  	r.mu.Lock()
   112  	r.ring = r.ring.Prev()
   113  	r.mu.Unlock()
   114  	return r
   115  }
   116  
   117  // Next returns the next ring element. r must not be empty.
   118  func (r *Ring) Next() *Ring {
   119  	r.mu.Lock()
   120  	r.ring = r.ring.Next()
   121  	r.mu.Unlock()
   122  	return r
   123  }
   124  
   125  // Link connects ring r with ring s such that r.Next()
   126  // becomes s and returns the original value for r.Next().
   127  // r must not be empty.
   128  //
   129  // If r and s point to the same ring, linking
   130  // them removes the elements between r and s from the ring.
   131  // The removed elements form a subring and the result is a
   132  // reference to that subring (if no elements were removed,
   133  // the result is still the original value for r.Next(),
   134  // and not nil).
   135  //
   136  // If r and s point to different rings, linking
   137  // them creates a single ring with the elements of s inserted
   138  // after r. The result points to the element following the
   139  // last element of s after insertion.
   140  //
   141  func (r *Ring) Link(s *Ring) *Ring {
   142  	r.mu.Lock()
   143  	s.mu.Lock()
   144  	r.ring.Link(s.ring)
   145  	s.mu.Unlock()
   146  	r.mu.Unlock()
   147  	r.dirty.Set(true)
   148  	s.dirty.Set(true)
   149  	return r
   150  }
   151  
   152  // Unlink removes n % r.Len() elements from the ring r, starting
   153  // at r.Next(). If n % r.Len() == 0, r remains unchanged.
   154  // The result is the removed subring. r must not be empty.
   155  //
   156  func (r *Ring) Unlink(n int) *Ring {
   157  	r.mu.Lock()
   158  	r.ring = r.ring.Unlink(n)
   159  	r.dirty.Set(true)
   160  	r.mu.Unlock()
   161  	return r
   162  }
   163  
   164  // RLockIteratorNext iterates and locks reading forward
   165  // with given callback function <f> within RWMutex.RLock.
   166  // If <f> returns true, then it continues iterating; or false to stop.
   167  func (r *Ring) RLockIteratorNext(f func(value interface{}) bool) {
   168  	r.mu.RLock()
   169  	defer r.mu.RUnlock()
   170  	if !f(r.ring.Value) {
   171  		return
   172  	}
   173  	for p := r.ring.Next(); p != r.ring; p = p.Next() {
   174  		if !f(p.Value) {
   175  			break
   176  		}
   177  	}
   178  }
   179  
   180  // RLockIteratorPrev iterates and locks reading backward
   181  // with given callback function <f> within RWMutex.RLock.
   182  // If <f> returns true, then it continues iterating; or false to stop.
   183  func (r *Ring) RLockIteratorPrev(f func(value interface{}) bool) {
   184  	r.mu.RLock()
   185  	defer r.mu.RUnlock()
   186  	if !f(r.ring.Value) {
   187  		return
   188  	}
   189  	for p := r.ring.Prev(); p != r.ring; p = p.Prev() {
   190  		if !f(p.Value) {
   191  			break
   192  		}
   193  	}
   194  }
   195  
   196  // LockIteratorNext iterates and locks writing forward
   197  // with given callback function <f> within RWMutex.RLock.
   198  // If <f> returns true, then it continues iterating; or false to stop.
   199  func (r *Ring) LockIteratorNext(f func(item *ring.Ring) bool) {
   200  	r.mu.RLock()
   201  	defer r.mu.RUnlock()
   202  	if !f(r.ring) {
   203  		return
   204  	}
   205  	for p := r.ring.Next(); p != r.ring; p = p.Next() {
   206  		if !f(p) {
   207  			break
   208  		}
   209  	}
   210  }
   211  
   212  // LockIteratorPrev iterates and locks writing backward
   213  // with given callback function <f> within RWMutex.RLock.
   214  // If <f> returns true, then it continues iterating; or false to stop.
   215  func (r *Ring) LockIteratorPrev(f func(item *ring.Ring) bool) {
   216  	r.mu.RLock()
   217  	defer r.mu.RUnlock()
   218  	if !f(r.ring) {
   219  		return
   220  	}
   221  	for p := r.ring.Prev(); p != r.ring; p = p.Prev() {
   222  		if !f(p) {
   223  			break
   224  		}
   225  	}
   226  }
   227  
   228  // SliceNext returns a copy of all item values as slice forward from current position.
   229  func (r *Ring) SliceNext() []interface{} {
   230  	s := make([]interface{}, 0)
   231  	r.mu.RLock()
   232  	if r.ring.Value != nil {
   233  		s = append(s, r.ring.Value)
   234  	}
   235  	for p := r.ring.Next(); p != r.ring; p = p.Next() {
   236  		if p.Value != nil {
   237  			s = append(s, p.Value)
   238  		}
   239  	}
   240  	r.mu.RUnlock()
   241  	return s
   242  }
   243  
   244  // SlicePrev returns a copy of all item values as slice backward from current position.
   245  func (r *Ring) SlicePrev() []interface{} {
   246  	s := make([]interface{}, 0)
   247  	r.mu.RLock()
   248  	if r.ring.Value != nil {
   249  		s = append(s, r.ring.Value)
   250  	}
   251  	for p := r.ring.Prev(); p != r.ring; p = p.Prev() {
   252  		if p.Value != nil {
   253  			s = append(s, p.Value)
   254  		}
   255  	}
   256  	r.mu.RUnlock()
   257  	return s
   258  }