mirror of
https://github.com/fumiama/orbyte.git
synced 2026-06-10 21:24:50 +08:00
init
This commit is contained in:
113
pool.go
Normal file
113
pool.go
Normal file
@@ -0,0 +1,113 @@
|
||||
// Package orbyte is a lightweight & safe (buffer-writer | general object) pool.
|
||||
package orbyte
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// Pool lightweight general pool.
|
||||
type Pool[T any] struct {
|
||||
pooler Pooler[T]
|
||||
pool sync.Pool
|
||||
countin int32
|
||||
countout int32
|
||||
isstrict bool
|
||||
}
|
||||
|
||||
// NewPool make a new pool from custom pooler.
|
||||
func NewPool[T any](pooler Pooler[T]) *Pool[T] {
|
||||
p := new(Pool[T])
|
||||
p.pooler = pooler
|
||||
p.pool.New = func() any {
|
||||
return &Item[T]{pool: p}
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// SetStrictMode panic on every misuse.
|
||||
//
|
||||
// Enable this to detect coding errors.
|
||||
func (pool *Pool[T]) SetStrictMode(on bool) {
|
||||
pool.isstrict = on
|
||||
}
|
||||
|
||||
func (pool *Pool[T]) incin() {
|
||||
atomic.AddInt32(&pool.countin, 1)
|
||||
}
|
||||
|
||||
func (pool *Pool[T]) decin() {
|
||||
atomic.AddInt32(&pool.countin, -1)
|
||||
}
|
||||
|
||||
func (pool *Pool[T]) incout() {
|
||||
atomic.AddInt32(&pool.countout, 1)
|
||||
}
|
||||
|
||||
func (pool *Pool[T]) decout() {
|
||||
atomic.AddInt32(&pool.countout, -1)
|
||||
}
|
||||
|
||||
func (pool *Pool[T]) newempty() *Item[T] {
|
||||
item := pool.pool.Get().(*Item[T])
|
||||
if item.stat.hasdestroyed() { // is recycled
|
||||
pool.decin()
|
||||
}
|
||||
item.stat = status(0)
|
||||
pool.incout()
|
||||
item.setautodestroy()
|
||||
return item
|
||||
}
|
||||
|
||||
func (pool *Pool[T]) put(item *Item[T]) {
|
||||
runtime.SetFinalizer(item, nil)
|
||||
|
||||
if pool.isstrict {
|
||||
return
|
||||
}
|
||||
|
||||
item.cfg = nil
|
||||
var dt T
|
||||
item.val = dt
|
||||
|
||||
pool.pool.Put(item)
|
||||
|
||||
pool.decout()
|
||||
pool.incin()
|
||||
}
|
||||
|
||||
// New call this to generate an item.
|
||||
func (pool *Pool[T]) New(config any) *Item[T] {
|
||||
item := pool.newempty()
|
||||
item.cfg = config
|
||||
item.stat.setbuffered(true)
|
||||
item.val = pool.pooler.New(config, item.val)
|
||||
return item
|
||||
}
|
||||
|
||||
// InvolveItem[T any] involve external object into pool.
|
||||
//
|
||||
// After that, you must only use the object through Item.
|
||||
func (pool *Pool[T]) Involve(config, obj any) *Item[T] {
|
||||
item := pool.newempty()
|
||||
item.cfg = config
|
||||
item.stat.setbuffered(true)
|
||||
item.val = pool.pooler.Parse(obj, item.val)
|
||||
return item
|
||||
}
|
||||
|
||||
// ParseItem[T any] safely convert obj into pool item without copy.
|
||||
//
|
||||
// You can still use the original object elsewhere.
|
||||
func (pool *Pool[T]) Parse(config, obj any) *Item[T] {
|
||||
item := pool.newempty()
|
||||
item.cfg = config
|
||||
item.val = pool.pooler.Parse(obj, item.val)
|
||||
return item
|
||||
}
|
||||
|
||||
// CountItems returns total item count outside and inside.
|
||||
func (pool *Pool[T]) CountItems() (outside, inside int32) {
|
||||
return atomic.LoadInt32(&pool.countout), atomic.LoadInt32(&pool.countin)
|
||||
}
|
||||
Reference in New Issue
Block a user