github.com/rolandhe/saber@v0.0.4/gocc/countdownlatch.go (about)

     1  // Golang concurrent tools like java juc.
     2  //
     3  // Copyright 2023 The saber Authors. All rights reserved.
     4  
     5  // Package gocc, 提供类似java juc的库能力。包括:
     6  //
     7  // Cond with timeout,相比于标准库Cond,它最典型的特点是支持timeout
     8  //
     9  // Future,类似java的Future,提交到任务执行器的任务可以被异步执行,调用者持有Future来获取异步执行的结果或者取消任务
    10  //
    11  // FutureGroup, 包含多个Future,可以在FutureGroup上等待所有的Future任务都执行完成,也可以取消任务,相比于在多个Future上一个个轮询,调用更加简单
    12  //
    13  // BlockingQueue, 支持并发调用的、并行安全的队列,强制有界
    14  //
    15  // Executor, 用于异步执行任务的执行器,强制指定并发数。要执行的任务提交给Executor后马上返回Future,调用者持有Future来获取最终结果,Executor内执行完成任务或者发现任务取消后会修改Future的内部状态
    16  //
    17  // Semaphore,信号量
    18  //
    19  // CountdownLatch, 倒计数
    20  package gocc
    21  
    22  import (
    23  	"sync/atomic"
    24  	"time"
    25  )
    26  
    27  // NewCountdownLatch 构建总量为count的倒计数,相比于WaitGroup, CountdownLatch提供的能力更丰富
    28  //
    29  //	count  数据总量
    30  func NewCountdownLatch(count int64) *CountdownLatch {
    31  	if count < 0 {
    32  		panic("invalid tokenCount value")
    33  	}
    34  	p := &CountdownLatch{
    35  		tokenCount: &atomic.Int64{},
    36  		notifier:   make(chan struct{}),
    37  	}
    38  	p.tokenCount.Add(count)
    39  	return p
    40  }
    41  
    42  // CountdownLatch ,类似java的CountdownLatch,实现倒计数功能,支持wait timeout
    43  type CountdownLatch struct {
    44  	tokenCount *atomic.Int64
    45  	notifier   chan struct{}
    46  }
    47  
    48  // Down 倒计数减一
    49  func (dw *CountdownLatch) Down() int64 {
    50  	if dw.tokenCount.Load() <= 0 {
    51  		return 0
    52  	}
    53  	v := dw.tokenCount.Add(-1)
    54  	if v == 0 {
    55  		close(dw.notifier)
    56  	}
    57  	if v < 0 {
    58  		v = 0
    59  	}
    60  	return v
    61  }
    62  
    63  // TryWait 尝试等待, 如果已经倒计数到0,则返回true,否则立即返回false
    64  func (dw *CountdownLatch) TryWait() bool {
    65  	select {
    66  	case <-dw.notifier:
    67  		return true
    68  	default:
    69  		return false
    70  	}
    71  }
    72  
    73  // Wait 等待,直到倒计数到0
    74  func (dw *CountdownLatch) Wait() {
    75  	<-dw.notifier
    76  }
    77  
    78  // WaitTimeout 带超时的等待倒计数到0,如果超时内倒计数到0,返回true,否则返回false
    79  func (dw *CountdownLatch) WaitTimeout(timeout time.Duration) bool {
    80  	select {
    81  	case <-dw.notifier:
    82  		return true
    83  	case <-time.After(timeout):
    84  		return false
    85  	}
    86  }