import (
"time"
- "sync"
+ "container/list"
+ syncmap "github.com/qydysky/part/map"
idpool "github.com/qydysky/part/idpool"
)
SumInDruation int64
Druation int64
now int64
- deleteNum int
pool *idpool.Idpool
- kvt_map map[string]tmplK_item
- sync.RWMutex
+ kvt_map syncmap.Map
+ slowBackList *list.List
}
type tmplK_item struct {
s := &tmplK{
SumInDruation:SumInDruation,
Druation:Druation,
- kvt_map:make(map[string]tmplK_item),
pool:idpool.New(),
+ slowBackList:list.New(),
}
go func(){
ticker := time.NewTicker(time.Second)
}
func (s *tmplK) Set(key string) (id uintptr) {
- s.Lock()
- defer s.Unlock()
- if tmp, oks := s.kvt_map[key];oks {
- defer s.pool.Put(tmp.uid)//在取得新Id后才put回
- } else if s.SumInDruation >= 0 && s.pool.Len() >= uint(s.SumInDruation){//不为无限&&达到限额 随机替代
- for oldkey,item := range s.kvt_map {
- s.kvt_map[key] = tmplK_item{
- kv: item.kv,
+ if tmp, oks := s.kvt_map.LoadV(key).(tmplK_item);oks {
+ s.free(tmp.uid)
+ } else if s.SumInDruation >= 0 && s.freeLen() >= s.SumInDruation{//不为无限&&达到限额 随机替代
+ s.kvt_map.Range(func(oldkey,item interface{})(bool){
+ id = item.(tmplK_item).kv
+ s.kvt_map.Store(key, tmplK_item{
+ kv: id,
kt: s.now,
- uid: item.uid,
- }
- delete(s.kvt_map,oldkey)
- return item.kv
- }
+ uid: item.(tmplK_item).uid,
+ })
+ s.kvt_map.Delete(oldkey)
+ return false
+ })
+ return
}
Uid := s.pool.Get()
- s.kvt_map[key] = tmplK_item{
+ s.kvt_map.Store(key, tmplK_item{
kv: Uid.Id,
kt: s.now,
uid: Uid,
- }
+ })
return Uid.Id
}
func (s *tmplK) Get(key string) (isLive bool,id uintptr){
- s.RLock()
- tmp, ok := s.kvt_map[key]
- s.RUnlock()
+ tmp, ok := s.kvt_map.Load(key)
- id = tmp.kv
- isLive = ok && s.Druation < 0 || s.now - tmp.kt <= s.Druation
+ item,_ := tmp.(tmplK_item)
+ id = item.kv
+
+ isLive = ok && s.Druation < 0 || s.now - item.kt <= s.Druation
if !isLive && ok {
- s.pool.Put(tmp.uid)
- s.Lock()
- delete(s.kvt_map,key)
- s.deleteNum += 0
- if s.deleteNum > len(s.kvt_map) {
- s.deleteNum = 0
- go s.Tidy()
- }
- s.Unlock()
+ s.free(item.uid)
+ s.kvt_map.Delete(key)
}
return
}
return ok && k == id
}
-func (s *tmplK) Buf() (int64,int) {
- return s.now,len(s.kvt_map)
+func (s *tmplK) Len() (int64,int) {
+ return s.now,s.kvt_map.Len()
}
-func (s *tmplK) Tidy() {
- tmp := make(map[string]tmplK_item)
- s.Lock()
- for k,v := range s.kvt_map {tmp[k] = v}
- s.kvt_map = tmp
- s.Unlock()
+func (s *tmplK) freeLen() (int64) {
+ return int64(int(s.pool.Len()) + s.slowBackList.Len())
+}
+
+func (s *tmplK) free(i *idpool.Id) {
+ s.slowBackList.PushBack(i)
+ if s.freeLen() > s.SumInDruation {
+ if el := s.slowBackList.Front();el != nil{
+ e := s.slowBackList.Remove(el)
+ s.pool.Put(e.(*idpool.Id))
+ }
+ }
}
\ No newline at end of file
"testing"
)
-func Test_tmplK(t *testing.T) {
+func Test_tmplK1(t *testing.T) {
s := New_tmplK(1e6, 5)
k1 := s.Set("a")
if !s.Check("a",k1) {t.Error(`no match1`)}
k2 := s.Set("a")
if s.Check("a",k1) {t.Error(`match`)}
if !s.Check("a",k2) {t.Error(`no match2`)}
- if o,p := s.Buf();p != 1 || o - time.Now().Unix() > 1{t.Error(`sum/time no match1`)}
+ if o,p := s.Len();p != 1 || o - time.Now().Unix() > 1{t.Error(`sum/time no match1`)}
- time.Sleep(time.Second*time.Duration(5))
+ time.Sleep(time.Second*time.Duration(6))
if s.Check("a",k1) {t.Error(`no TO1`)}
- if s.Check("a",k1) {t.Error(`no TO2`)}
+ if s.Check("a",k2) {t.Error(`no TO2`)}
- if o,p := s.Buf();p != 0 || o - time.Now().Unix() > 1{t.Error(`sum/time no match2`)}
+ if o,p := s.Len();p != 0 || o - time.Now().Unix() > 1{t.Error(`sum/time no match2`,p)}
}
func Test_tmplK2(t *testing.T) {