github.com/gogf/gf/v2@v2.7.4/container/gring/gring.go (about)

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