2019-02-03 01:25:00 -08:00
|
|
|
package lib
|
2019-01-27 22:45:55 -08:00
|
|
|
|
|
|
|
import (
|
|
|
|
"sync/atomic"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Rate struct {
|
|
|
|
bucketSize int64 //木桶容量
|
|
|
|
bucketSurplusSize int64 //当前桶中体积
|
|
|
|
bucketAddSize int64 //每次加水大小
|
|
|
|
stopChan chan bool //停止
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewRate(addSize int64) *Rate {
|
|
|
|
return &Rate{
|
|
|
|
bucketSize: addSize * 2,
|
|
|
|
bucketSurplusSize: 0,
|
|
|
|
bucketAddSize: addSize,
|
|
|
|
stopChan: make(chan bool),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Rate) Start() {
|
|
|
|
go s.session()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Rate) add(size int64) {
|
|
|
|
if (s.bucketSize - s.bucketSurplusSize) < s.bucketAddSize {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
atomic.AddInt64(&s.bucketSurplusSize, size)
|
|
|
|
}
|
|
|
|
|
|
|
|
//回桶
|
|
|
|
func (s *Rate) ReturnBucket(size int64) {
|
|
|
|
s.add(size)
|
|
|
|
}
|
|
|
|
|
|
|
|
//停止
|
|
|
|
func (s *Rate) Stop() {
|
|
|
|
s.stopChan <- true
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Rate) Get(size int64) {
|
|
|
|
if s.bucketSurplusSize >= size {
|
|
|
|
atomic.AddInt64(&s.bucketSurplusSize, -size)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
ticker := time.NewTicker(time.Millisecond * 100)
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-ticker.C:
|
|
|
|
if s.bucketSurplusSize >= size {
|
|
|
|
atomic.AddInt64(&s.bucketSurplusSize, -size)
|
|
|
|
ticker.Stop()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Rate) session() {
|
|
|
|
ticker := time.NewTicker(time.Second * 1)
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-ticker.C:
|
|
|
|
s.add(s.bucketAddSize)
|
|
|
|
case <-s.stopChan:
|
|
|
|
ticker.Stop()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|