github.com/egonelbre/exp@v0.0.0-20240430123955-ed1d3aa93911/queue/blockfreequeue/queue.go (about)

     1  package blockfreequeue
     2  
     3  const (
     4  	BlockSize = 1024
     5  	BlockMask = BlockSize - 1
     6  )
     7  
     8  type Queue struct {
     9  	headx  uint32
    10  	tailx  uint32
    11  	head   *Block
    12  	tail   *Block
    13  	free   *Block
    14  	blocks uint32
    15  }
    16  
    17  type Block struct {
    18  	Items [BlockSize]interface{}
    19  	Next  *Block
    20  }
    21  
    22  func New() *Queue { return &Queue{} }
    23  
    24  func (q *Queue) Len() int {
    25  	return int(q.blocks)*BlockSize - BlockSize + int(q.tailx) - int(q.headx)
    26  }
    27  
    28  func (q *Queue) newBlock() *Block {
    29  	block := q.free
    30  	if block == nil {
    31  		return &Block{}
    32  	} else {
    33  		q.free = nil
    34  	}
    35  	return block
    36  }
    37  
    38  func (q *Queue) tailBlock() *Block {
    39  	if q.tail != nil {
    40  		return q.tail
    41  	}
    42  
    43  	q.tail = q.newBlock()
    44  	q.head = q.tail
    45  
    46  	return q.tail
    47  }
    48  
    49  func (q *Queue) Push(v interface{}) {
    50  	first := q.tailBlock()
    51  	first.Items[q.tailx&BlockMask] = v
    52  	q.tailx++
    53  	if q.tailx == BlockSize {
    54  		q.tailx = 0
    55  		tail := q.tail
    56  		q.tail = q.newBlock()
    57  		tail.Next = q.tail
    58  		q.blocks++
    59  	}
    60  }
    61  
    62  func (q *Queue) Pop() (interface{}, bool) {
    63  	if q.head == nil {
    64  		return nil, false
    65  	}
    66  
    67  	value := q.head.Items[q.headx&BlockMask]
    68  	q.head.Items[q.headx&BlockMask] = nil
    69  	q.headx++
    70  	if q.headx == BlockSize {
    71  		q.headx = 0
    72  		q.blocks--
    73  		q.free, q.head = q.head, q.head.Next
    74  		q.free.Next = nil
    75  	}
    76  
    77  	return value, true
    78  }