go test -count 1 -timeout 5s -v -race github.com/qydysky/part/component2
go test -count 1 -timeout 20s -v -race github.com/qydysky/part/ctx
go test -count 1 -timeout 10s -v -race github.com/qydysky/part/slice
+ go test -count 1 -timeout 10s -v github.com/qydysky/part/slice
go test -count 1 -timeout 5s -v -race github.com/qydysky/part/bools
go test -count 1 -timeout 5s -v -race github.com/qydysky/part/errors
go test -count 1 -timeout 5s -v -race github.com/qydysky/part/crypto/...
go test -count 1 -timeout 5s -v -race github.com/qydysky/part/component2
go test -count 1 -timeout 20s -v -race github.com/qydysky/part/ctx
go test -count 1 -timeout 10s -v -race github.com/qydysky/part/slice
+ go test -count 1 -timeout 10s -v github.com/qydysky/part/slice
go test -count 1 -timeout 5s -v -race github.com/qydysky/part/bools
go test -count 1 -timeout 5s -v -race github.com/qydysky/part/errors
go test -count 1 -timeout 5s -v -race github.com/qydysky/part/crypto/...
go test -count 1 -timeout 5s -v -race github.com/qydysky/part/component2
go test -count 1 -timeout 20s -v -race github.com/qydysky/part/ctx
go test -count 1 -timeout 10s -v -race github.com/qydysky/part/slice
+ go test -count 1 -timeout 10s -v github.com/qydysky/part/slice
go test -count 1 -timeout 5s -v -race github.com/qydysky/part/bools
go test -count 1 -timeout 5s -v -race github.com/qydysky/part/errors
go test -count 1 -timeout 5s -v -race github.com/qydysky/part/crypto/...
"unsafe"
)
-type Idpool struct {
+type Idpool[T any] struct {
pool sync.Pool
sum int64
- initF func() interface{}
+ initF func() *T
}
-type Id struct {
+type Id[T any] struct {
Id uintptr
- Item interface{}
+ Item *T
}
-func New(f func() interface{}) *Idpool {
- return &Idpool{
+func New[T any](f func() *T) *Idpool[T] {
+ return &Idpool[T]{
initF: f,
pool: sync.Pool{
- New: func() interface{} {
- var o = new(Id)
+ New: func() any {
+ var o = new(Id[T])
o.Item = f()
o.Id = uintptr(unsafe.Pointer(&o.Item))
return o
}
}
-func (t *Idpool) Get() (o *Id) {
- o = t.pool.Get().(*Id)
+func (t *Idpool[T]) Get() (o *Id[T]) {
+ o = t.pool.Get().(*Id[T])
if o.Item == nil {
o.Item = t.initF()
o.Id = uintptr(unsafe.Pointer(&o.Item))
return
}
-func (t *Idpool) Put(i *Id) {
- if i.Item == nil {
- return
+func (t *Idpool[T]) Put(is ...*Id[T]) {
+ for _, i := range is {
+ if i.Item == nil {
+ continue
+ }
+ t.pool.Put(i)
+ atomic.AddInt64(&t.sum, -1)
}
- t.pool.Put(i)
- atomic.AddInt64(&t.sum, -1)
}
-func (t *Idpool) Len() int64 {
+func (t *Idpool[T]) InUse() int64 {
return atomic.LoadInt64(&t.sum)
}
type test struct{}
func Test(t *testing.T) {
- pool := New(func() interface{} {
+ pool := New(func() *test {
return &test{}
})
a := pool.Get()
b := pool.Get()
- t.Log(a.Id, a.Item, pool.Len())
- t.Log(b.Id, b.Item)
- pool.Put(a)
- pool.Put(a)
- t.Log(a.Id, a.Item, pool.Len())
- t.Log(b.Id, b.Item)
+ if pool.InUse() != 2 {
+ t.Fatal()
+ }
+ bid := b.Id
+ pool.Put(b)
+ if pool.InUse() != 1 {
+ t.Fatal()
+ }
a = pool.Get()
- t.Log(a.Id, a.Item, pool.Len())
- t.Log(b.Id, b.Item)
+ if bid != a.Id {
+ t.Fatal()
+ }
}
import (
"errors"
"runtime"
+ "sync"
)
type noCopy struct{}
}
}
+type FlexBlocksI[T any] interface {
+ // // eg
+ //
+ // if tmpbuf, putBack, e := buf.Get(); e == nil {
+ // tmpbuf = append(tmpbuf[:0], b...)
+ // // do something with tmpbuf
+ // putBack(tmpbuf)
+ // }
+ Get() ([]T, func([]T), error)
+}
+
type flexBlocks[T any] struct {
_ noCopy
free chan int
buf [][]T
}
-func NewFlexBlocks[T any](blockNum int) BlocksI[T] {
+func NewFlexBlocks[T any](blockNum int) FlexBlocksI[T] {
p := &flexBlocks[T]{
free: make(chan int, blockNum+1),
buf: make([][]T, blockNum),
return p
}
-func (t *flexBlocks[T]) Get() ([]T, func(), error) {
+func (t *flexBlocks[T]) Get() ([]T, func([]T), error) {
select {
case offset := <-t.free:
- return t.buf[offset], func() {
+ return t.buf[offset], func(ts []T) {
+ t.buf[offset] = ts
t.free <- offset
}, nil
default:
- return nil, func() {}, ErrOverflow
+ return nil, func(_ []T) {}, ErrOverflow
}
}
-func (t *flexBlocks[T]) GetAuto() (b []T, e error) {
- select {
- case offset := <-t.free:
- b = t.buf[offset]
- runtime.AddCleanup(&b, func(offset int) {
- t.free <- offset
- }, offset)
- return
- default:
- return nil, ErrOverflow
+type PoolBlocksI[T any] interface {
+ // // eg
+ //
+ // if tmpbuf, putBack, e := buf.Get(); e == nil {
+ // tmpbuf = append(tmpbuf[:0], b...)
+ // // do something with tmpbuf
+ // putBack(tmpbuf)
+ // }
+ Get() ([]T, func([]T), error)
+}
+
+type poolBlocks[T any] struct {
+ pool sync.Pool
+}
+
+func NewPoolBlocks[T any]() PoolBlocksI[T] {
+ t := &poolBlocks[T]{}
+ t.pool.New = func() any {
+ return []T{}
}
+ return t
+}
+
+func (t *poolBlocks[T]) Get() ([]T, func([]T), error) {
+ return t.pool.Get().([]T), func(ts []T) {
+ t.pool.Put(ts)
+ }, nil
}
--- /dev/null
+//go:build !race
+
+package part
+
+import (
+ "runtime/debug"
+ "testing"
+)
+
+func TestMain3(t *testing.T) {
+ defer debug.SetGCPercent(debug.SetGCPercent(-1))
+ buf := NewPoolBlocks[byte]()
+ if tmpbuf, putBack, e := buf.Get(); e == nil {
+ tmpbuf = append(tmpbuf[:0], []byte("123")...)
+ // do something with tmpbuf
+ putBack(tmpbuf)
+ } else {
+ t.Fail()
+ }
+ if tmpbuf, putBack, e := buf.Get(); e == nil {
+ if cap(tmpbuf) != 8 {
+ t.Fatal()
+ }
+ tmpbuf = append(tmpbuf[:0], []byte("123")...)
+ // do something with tmpbuf
+ putBack(tmpbuf)
+ } else {
+ t.Fail()
+ }
+}
"testing"
)
+func TestMain4(t *testing.T) {
+ buf := NewFlexBlocks[byte](1)
+ if tmpbuf, putBack, e := buf.Get(); e == nil {
+ tmpbuf = append(tmpbuf[:0], []byte("123")...)
+ // do something with tmpbuf
+ putBack(tmpbuf)
+ } else {
+ t.Fail()
+ }
+ if tmpbuf, putBack, e := buf.Get(); e == nil {
+ if cap(tmpbuf) != 8 {
+ t.Fatal()
+ }
+ tmpbuf = append(tmpbuf[:0], []byte("123")...)
+ // do something with tmpbuf
+ putBack(tmpbuf)
+ } else {
+ t.Fail()
+ }
+}
+
func TestMain(t *testing.T) {
buf := NewBlocks[byte](1024, 1)
if tmpbuf, putBack, e := buf.Get(); e == nil {
SumInDruation int64
Druation int64
now int64
- pool *idpool.Idpool
+ pool *idpool.Idpool[struct{}]
kvt_map syncmap.Map
slowBackList *list.List
}
type tmplK_item struct {
kv uintptr
kt int64
- uid *idpool.Id
+ uid *idpool.Id[struct{}]
}
func New_tmplK(SumInDruation, Druation int64) *tmplK {
s := &tmplK{
SumInDruation: SumInDruation,
Druation: Druation,
- pool: idpool.New(func() interface{} { return new(struct{}) }),
+ pool: idpool.New(func() *struct{} { return new(struct{}) }),
slowBackList: list.New(),
}
go func() {
}
func (s *tmplK) freeLen() int64 {
- return int64(int(s.pool.Len()) + s.slowBackList.Len())
+ return int64(int(s.pool.InUse()) + s.slowBackList.Len())
}
-func (s *tmplK) free(i *idpool.Id) {
+func (s *tmplK) free(i *idpool.Id[struct{}]) {
s.slowBackList.PushBack(i)
if s.freeLen() > s.SumInDruation {
if el := s.slowBackList.Front(); el != nil && el.Value != nil {
e := s.slowBackList.Remove(el)
- s.pool.Put(e.(*idpool.Id))
+ s.pool.Put(e.(*idpool.Id[struct{}]))
}
}
}
Druation int64
now int64
deleteNum int
- pool *idpool.Idpool
+ pool *idpool.Idpool[struct{}]
kvt_map map[uintptr]tmplV_item
sync.RWMutex
}
type tmplV_item struct {
kv string
kt int64
- uid *idpool.Id
+ uid *idpool.Id[struct{}]
}
func New_tmplV(SumInDruation, Druation int64) *tmplV {
SumInDruation: SumInDruation,
Druation: Druation,
kvt_map: make(map[uintptr]tmplV_item),
- pool: idpool.New(func() interface{} { return new(struct{}) }),
+ pool: idpool.New(func() *struct{} { return new(struct{}) }),
}
go func() {
ticker := time.NewTicker(time.Second)
func (s *tmplV) Set(contect string) (key uintptr) {
- if s.SumInDruation >= 0 && s.pool.Len() >= s.SumInDruation { //不为无限&&达到限额 随机替代
+ if s.SumInDruation >= 0 && s.pool.InUse() >= s.SumInDruation { //不为无限&&达到限额 随机替代
s.Lock()
for key, item := range s.kvt_map {
s.kvt_map[key] = tmplV_item{
Type: websocket.PongMessage,
Msg: func(f func([]byte) error) error {
f(tmpbuf)
- putBack()
+ putBack(tmpbuf)
return nil
},
})
Type: websocket.TextMessage,
Msg: func(f func([]byte) error) error {
f(tmpbuf)
- putBack()
+ putBack(tmpbuf)
return nil
},
})
type Server struct {
ws_mq *mq.Msgq
- userpool *idpool.Idpool
+ userpool *idpool.Idpool[struct{}]
m sync.Mutex
}
func New_server() *Server {
return &Server{
- ws_mq: mq.New(), //收发通道
- userpool: idpool.New(func() interface{} { return new(struct{}) }), //浏览器标签页池
+ ws_mq: mq.New(), //收发通道
+ userpool: idpool.New(func() *struct{} { return new(struct{}) }), //浏览器标签页池
}
}
}
func (t *Server) Len() int64 {
- return t.userpool.Len()
+ return t.userpool.InUse()
}