gitee.com/h79/goutils@v1.22.10/common/queue/circular.go (about)

     1  package queue
     2  
     3  type ResetFunc func()
     4  
     5  var _ Queue = (*Circular)(nil)
     6  
     7  // Circular 环型队列
     8  type Circular struct {
     9  	resetFunc ResetFunc
    10  	items     []any
    11  	head      int
    12  	tail      int
    13  	size      int
    14  	isFull    bool
    15  }
    16  
    17  func NewCircular(size int, resetFunc ResetFunc) *Circular {
    18  	return &Circular{
    19  		resetFunc: resetFunc,
    20  		items:     make([]any, size),
    21  		size:      size,
    22  	}
    23  }
    24  
    25  func (cr *Circular) Add(it any) error {
    26  	if cr.size == 0 {
    27  		return ErrIsReleased
    28  	}
    29  	if cr.isFull {
    30  		return ErrIsFull
    31  	}
    32  	cr.items[cr.tail] = it
    33  	cr.tail++
    34  
    35  	if cr.tail == cr.size {
    36  		cr.tail = 0
    37  	}
    38  	if cr.tail == cr.head {
    39  		cr.isFull = true
    40  	}
    41  	return nil
    42  }
    43  
    44  func (cr *Circular) Push(it any) error {
    45  	return cr.Add(it)
    46  }
    47  
    48  func (cr *Circular) Pop() any {
    49  	if cr.Empty() {
    50  		return nil
    51  	}
    52  	w := cr.items[cr.head]
    53  	cr.items[cr.head] = nil
    54  	cr.head++
    55  	if cr.head == cr.size {
    56  		cr.head = 0
    57  	}
    58  	cr.isFull = false
    59  	return w
    60  }
    61  
    62  func (cr *Circular) Peek() any {
    63  	if cr.Empty() {
    64  		return nil
    65  	}
    66  	return cr.items[cr.head]
    67  }
    68  
    69  func (cr *Circular) Len() int {
    70  	if cr.size == 0 {
    71  		return 0
    72  	}
    73  
    74  	if cr.head == cr.tail {
    75  		if cr.isFull {
    76  			return cr.size
    77  		}
    78  		return 0
    79  	}
    80  
    81  	if cr.tail > cr.head {
    82  		return cr.tail - cr.head
    83  	}
    84  
    85  	return cr.size - cr.head + cr.tail
    86  }
    87  
    88  // Find return index -1 not found.
    89  func (cr *Circular) Find(fn IndexFunc) (any, int) {
    90  	var (
    91  		cursor = -1
    92  		va     any
    93  	)
    94  	for {
    95  		va, cursor = cr.Next(cursor)
    96  		if cursor == -1 {
    97  			break
    98  		}
    99  		if fn(va, cursor) {
   100  			return va, cursor
   101  		}
   102  	}
   103  	return nil, -1
   104  }
   105  
   106  func (cr *Circular) Foreach(fn IndexFunc) {
   107  	var (
   108  		cursor = -1
   109  		va     any
   110  	)
   111  	for {
   112  		va, cursor = cr.Next(cursor)
   113  		if cursor == -1 {
   114  			break
   115  		}
   116  		if fn(va, cursor) {
   117  			return
   118  		}
   119  	}
   120  }
   121  
   122  func (cr *Circular) Empty() bool {
   123  	return cr.head == cr.tail && !cr.isFull
   124  }
   125  
   126  func (cr *Circular) Next(index int) (any, int) {
   127  	if cr.Empty() {
   128  		return nil, -1
   129  	}
   130  	if index < 0 {
   131  		index = cr.head
   132  	}
   133  	if index == cr.tail {
   134  		return nil, -1
   135  	}
   136  	w := cr.items[index]
   137  	index++
   138  	if index == cr.size {
   139  		index = 0
   140  	}
   141  	return w, index
   142  }
   143  
   144  func (cr *Circular) Reset() {
   145  	if cr.Empty() {
   146  		return
   147  	}
   148  	if cr.resetFunc != nil {
   149  		cr.resetFunc()
   150  	}
   151  	cr.items = make([]any, cr.size)
   152  	cr.head = 0
   153  	cr.tail = 0
   154  }