github.com/bruceshao/lockfree@v1.1.3-0.20230816090528-e89824c0a6e9/lockfree.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  	"sync/atomic"
    13  )
    14  
    15  // Lockfree 包装类,内部包装了生产者和消费者
    16  type Lockfree[T any] struct {
    17  	writer   *Producer[T]
    18  	consumer *consumer[T]
    19  	status   int32
    20  }
    21  
    22  // NewLockfree 自定义创建消费端的Disruptor
    23  // capacity:buffer的容量大小,类似于chan的大小,但要求必须是2^n,即2的指数倍,如果不是的话会被修改
    24  // handler:消费端的事件处理器
    25  // blocks:读取阻塞时的处理策略
    26  func NewLockfree[T any](capacity int, handler EventHandler[T], blocks blockStrategy) *Lockfree[T] {
    27  	// 重新计算正确的容量
    28  	capacity = minSuitableCap(capacity)
    29  	seqer := newSequencer(capacity)
    30  	rbuf := newRingBuffer[T](capacity)
    31  	cmer := newConsumer[T](rbuf, handler, seqer, blocks)
    32  	writer := newProducer[T](seqer, rbuf, blocks)
    33  	return &Lockfree[T]{
    34  		writer:   writer,
    35  		consumer: cmer,
    36  		status:   READY,
    37  	}
    38  }
    39  
    40  func (d *Lockfree[T]) Start() error {
    41  	if atomic.CompareAndSwapInt32(&d.status, READY, RUNNING) {
    42  		// 启动消费者
    43  		if err := d.consumer.start(); err != nil {
    44  			// 恢复现场
    45  			atomic.CompareAndSwapInt32(&d.status, RUNNING, READY)
    46  			return err
    47  		}
    48  		// 启动生产者
    49  		if err := d.writer.start(); err != nil {
    50  			// 恢复现场
    51  			atomic.CompareAndSwapInt32(&d.status, RUNNING, READY)
    52  			return err
    53  		}
    54  		return nil
    55  	}
    56  	return fmt.Errorf(StartErrorFormat, "Disruptor")
    57  }
    58  
    59  func (d *Lockfree[T]) Producer() *Producer[T] {
    60  	return d.writer
    61  }
    62  
    63  func (d *Lockfree[T]) Running() bool {
    64  	return d.status == RUNNING
    65  }
    66  
    67  func (d *Lockfree[T]) Close() error {
    68  	if atomic.CompareAndSwapInt32(&d.status, RUNNING, READY) {
    69  		// 关闭生产者
    70  		if err := d.writer.close(); err != nil {
    71  			// 恢复现场
    72  			atomic.CompareAndSwapInt32(&d.status, READY, RUNNING)
    73  			return err
    74  		}
    75  		// 关闭消费者
    76  		if err := d.consumer.close(); err != nil {
    77  			// 恢复现场
    78  			atomic.CompareAndSwapInt32(&d.status, READY, RUNNING)
    79  			return err
    80  		}
    81  		// 关闭成功
    82  		return nil
    83  	}
    84  	return fmt.Errorf(CloseErrorFormat, "Disruptor")
    85  }