github.com/bruceshao/lockfree@v1.1.3-0.20230816090528-e89824c0a6e9/consumer.go (about) 1 /* 2 * Copyright (C) THL A29 Limited, a Tencent company. All rights reserved. 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 * 6 */ 7 8 package lockfree 9 10 import ( 11 "fmt" 12 "runtime" 13 "sync/atomic" 14 ) 15 16 // consumer 消费者,这个消费者只会有一个g操作,这样处理的好处是可以不涉及并发操作,其内部不会涉及到任何锁 17 // 对于实际的并发操作由该g进行分配 18 type consumer[T any] struct { 19 status int32 // 运行状态 20 rbuf *ringBuffer[T] 21 seqer *sequencer 22 blocks blockStrategy 23 hdl EventHandler[T] 24 } 25 26 func newConsumer[T any](rbuf *ringBuffer[T], hdl EventHandler[T], sequer *sequencer, blocks blockStrategy) *consumer[T] { 27 return &consumer[T]{ 28 rbuf: rbuf, 29 seqer: sequer, 30 hdl: hdl, 31 blocks: blocks, 32 status: READY, 33 } 34 } 35 36 func (c *consumer[T]) start() error { 37 if atomic.CompareAndSwapInt32(&c.status, READY, RUNNING) { 38 go c.handle() 39 return nil 40 } 41 return fmt.Errorf(StartErrorFormat, "Consumer") 42 } 43 44 func (c *consumer[T]) handle() { 45 // 判断是否可以获取到 46 rc := c.seqer.nextRead() 47 for { 48 if c.closed() { 49 return 50 } 51 var i = 0 52 for { 53 if c.closed() { 54 return 55 } 56 // 看下读取位置的seq是否OK 57 if v, p, exist := c.rbuf.contains(rc - 1); exist { 58 rc = c.seqer.readIncrement() 59 c.hdl.OnEvent(v) 60 i = 0 61 break 62 } else { 63 if i < spin { 64 procyield(30) 65 } else if i < spin+passiveSpin { 66 runtime.Gosched() 67 } else { 68 c.blocks.block(p, rc) 69 i = 0 70 } 71 i++ 72 } 73 } 74 } 75 } 76 77 func (c *consumer[T]) close() error { 78 if atomic.CompareAndSwapInt32(&c.status, RUNNING, READY) { 79 // 防止阻塞无法释放 80 c.blocks.release() 81 return nil 82 } 83 return fmt.Errorf(CloseErrorFormat, "Consumer") 84 } 85 86 // closed 判断是否已关闭 87 // 将直接判断调整为原子操作,解决data race问题 88 func (c *consumer[T]) closed() bool { 89 return atomic.LoadInt32(&c.status) == READY 90 }