github.com/cloudwego/kitex@v0.9.0/pkg/event/queue.go (about)

     1  /*
     2   * Copyright 2021 CloudWeGo Authors
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package event
    18  
    19  import (
    20  	"sync"
    21  )
    22  
    23  const (
    24  	// MaxEventNum is the default size of a event queue.
    25  	MaxEventNum = 200
    26  )
    27  
    28  // Queue is a ring to collect events.
    29  type Queue interface {
    30  	Push(e *Event)
    31  	Dump() interface{}
    32  }
    33  
    34  // queue implements a fixed size Queue.
    35  type queue struct {
    36  	ring        []*Event
    37  	tail        uint32
    38  	tailVersion map[uint32]*uint32
    39  	mu          sync.RWMutex
    40  }
    41  
    42  // NewQueue creates a queue with the given capacity.
    43  func NewQueue(cap int) Queue {
    44  	q := &queue{
    45  		ring:        make([]*Event, cap),
    46  		tailVersion: make(map[uint32]*uint32, cap),
    47  	}
    48  	for i := 0; i <= cap; i++ {
    49  		t := uint32(0)
    50  		q.tailVersion[uint32(i)] = &t
    51  	}
    52  	return q
    53  }
    54  
    55  // Push pushes an event to the queue.
    56  func (q *queue) Push(e *Event) {
    57  	q.mu.Lock()
    58  	defer q.mu.Unlock()
    59  
    60  	q.ring[q.tail] = e
    61  
    62  	newVersion := (*(q.tailVersion[q.tail])) + 1
    63  	q.tailVersion[q.tail] = &newVersion
    64  
    65  	q.tail = (q.tail + 1) % uint32(len(q.ring))
    66  }
    67  
    68  // Dump dumps the previously pushed events out in a reversed order.
    69  func (q *queue) Dump() interface{} {
    70  	q.mu.RLock()
    71  	defer q.mu.RUnlock()
    72  	results := make([]*Event, 0, len(q.ring))
    73  	pos := int32(q.tail)
    74  	for i := 0; i < len(q.ring); i++ {
    75  		pos--
    76  		if pos < 0 {
    77  			pos = int32(len(q.ring) - 1)
    78  		}
    79  
    80  		e := q.ring[pos]
    81  		if e == nil {
    82  			return results
    83  		}
    84  
    85  		results = append(results, e)
    86  	}
    87  
    88  	return results
    89  }