go_dreamfactory/lego/sys/blockcache/cache.go
2022-06-07 20:18:22 +08:00

135 lines
3.1 KiB
Go

package blockcache
import (
"sync"
"sync/atomic"
"unsafe"
"go_dreamfactory/lego/utils/container"
)
func newSys(options Options) (sys *Cache, err error) {
sys = &Cache{
options: options,
inpip: make(chan interface{}),
outpip: make(chan interface{}),
outnotic: make(chan struct{}),
element: container.NewLKQueue(),
free: options.CacheMaxSzie,
}
go sys.run()
return
}
type Item struct {
Size int64
Value interface{}
}
type Cache struct {
options Options
inpip chan interface{}
outpip chan interface{}
outnotic chan struct{}
instate int32
outruning int32
element *container.LKQueue
free int64
close int32
wg sync.WaitGroup
}
func (this *Cache) In() chan<- interface{} {
return this.inpip
}
func (this *Cache) Out() <-chan interface{} {
return this.outpip
}
func (this *Cache) Close() {
atomic.StoreInt32(&this.close, 1)
close(this.inpip)
close(this.outnotic)
this.wg.Wait()
close(this.outpip)
}
func (this *Cache) run() {
for v := range this.inpip {
siez := int64(unsafe.Sizeof(v))
if siez > this.options.CacheMaxSzie { //异常数据
this.Errorf("item size:%d large CacheMaxSzie:%d", siez, this.options.CacheMaxSzie)
continue
} else if siez > atomic.LoadInt64(&this.free) { //空间不足
atomic.StoreInt32(&this.instate, 1)
locp:
for _ = range this.outnotic {
if siez > atomic.LoadInt64(&this.free) {
atomic.StoreInt32(&this.instate, 1)
} else {
this.element.Enqueue(&Item{Size: siez, Value: v})
atomic.AddInt64(&this.free, -1*siez)
break locp
}
}
} else {
this.element.Enqueue(&Item{Size: siez, Value: v})
atomic.AddInt64(&this.free, -1*siez)
}
if atomic.CompareAndSwapInt32(&this.outruning, 0, 1) {
this.wg.Add(1)
go func() {
locp:
for {
v := this.element.Dequeue()
if v != nil && atomic.LoadInt32(&this.close) == 0 {
item := v.(*Item)
atomic.AddInt64(&this.free, item.Size)
if atomic.CompareAndSwapInt32(&this.instate, 1, 0) {
this.outnotic <- struct{}{}
}
this.outpip <- item.Value
} else {
break locp
}
}
atomic.StoreInt32(&this.outruning, 0)
this.wg.Done()
}()
}
}
}
///日志***********************************************************************
func (this *Cache) Debugf(format string, a ...interface{}) {
if this.options.Debug {
this.options.Log.Debugf("[SYS BlockCache] "+format, a)
}
}
func (this *Cache) Infof(format string, a ...interface{}) {
if this.options.Debug {
this.options.Log.Infof("[SYS BlockCache] "+format, a)
}
}
func (this *Cache) Warnf(format string, a ...interface{}) {
if this.options.Debug {
this.options.Log.Warnf("[SYS BlockCache] "+format, a)
}
}
func (this *Cache) Errorf(format string, a ...interface{}) {
if this.options.Debug {
this.options.Log.Errorf("[SYS BlockCache] "+format, a)
}
}
func (this *Cache) Panicf(format string, a ...interface{}) {
if this.options.Debug {
this.options.Log.Panicf("[SYS BlockCache] "+format, a)
}
}
func (this *Cache) Fatalf(format string, a ...interface{}) {
if this.options.Debug {
this.options.Log.Fatalf("[SYS BlockCache] "+format, a)
}
}