github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/module/mempool/queue/heroQueue.go (about) 1 package queue 2 3 import ( 4 "sync" 5 6 "github.com/rs/zerolog" 7 8 "github.com/onflow/flow-go/model/flow" 9 "github.com/onflow/flow-go/module" 10 herocache "github.com/onflow/flow-go/module/mempool/herocache/backdata" 11 "github.com/onflow/flow-go/module/mempool/herocache/backdata/heropool" 12 ) 13 14 // HeroQueue implements a HeroCache-based in-memory queue. 15 // HeroCache is a key-value cache with zero heap allocation and optimized Garbage Collection. 16 type HeroQueue struct { 17 mu sync.RWMutex 18 cache *herocache.Cache 19 sizeLimit uint 20 } 21 22 func NewHeroQueue(sizeLimit uint32, logger zerolog.Logger, collector module.HeroCacheMetrics, 23 ) *HeroQueue { 24 return &HeroQueue{ 25 cache: herocache.NewCache( 26 sizeLimit, 27 herocache.DefaultOversizeFactor, 28 heropool.NoEjection, 29 logger.With().Str("mempool", "hero-queue").Logger(), 30 collector), 31 sizeLimit: uint(sizeLimit), 32 } 33 } 34 35 // Push stores the entity into the queue. 36 // Boolean returned variable determines whether push was successful, i.e., 37 // push may be dropped if queue is full or already exists. 38 func (c *HeroQueue) Push(entity flow.Entity) bool { 39 c.mu.Lock() 40 defer c.mu.Unlock() 41 42 if c.cache.Size() >= c.sizeLimit { 43 // we check size before attempt on a push, 44 // although HeroCache is on no-ejection mode and discards pushes beyond limit, 45 // we save an id computation by just checking the size here. 46 return false 47 } 48 49 return c.cache.Add(entity.ID(), entity) 50 } 51 52 // Pop removes and returns the head of queue, and updates the head to the next element. 53 // Boolean return value determines whether pop is successful, i.e., popping an empty queue returns false. 54 func (c *HeroQueue) Pop() (flow.Entity, bool) { 55 c.mu.Lock() 56 defer c.mu.Unlock() 57 58 head, ok := c.cache.Head() 59 if !ok { 60 // cache is empty, and there is no head yet to pop. 61 return nil, false 62 } 63 64 c.cache.Remove(head.ID()) 65 return head, true 66 } 67 68 func (c *HeroQueue) Size() uint { 69 c.mu.RLock() 70 defer c.mu.RUnlock() 71 72 return c.cache.Size() 73 }