mirror of
https://github.com/fumiama/orbyte.git
synced 2026-06-09 12:40:34 +08:00
optimize: change Destroy -> ManualDestroy
This commit is contained in:
7
item.go
7
item.go
@@ -104,8 +104,11 @@ func (b *Item[T]) destroybystat(stat status) {
|
||||
b.pool.put(b)
|
||||
}
|
||||
|
||||
// Destroy item and put it back to pool.
|
||||
func (b *Item[T]) Destroy() {
|
||||
// ManualDestroy item and put it back to pool.
|
||||
//
|
||||
// Calling this method without setting pool.SetManualDestroy(true)
|
||||
// can probably cause panic.
|
||||
func (b *Item[T]) ManualDestroy() {
|
||||
b.destroybystat(status(atomic.SwapUintptr(
|
||||
(*uintptr)(&b.stat), uintptr(destroyedstatus),
|
||||
)))
|
||||
|
||||
@@ -42,7 +42,7 @@ func testBuffer(buf *orbyte.Item[bytes.Buffer], t *testing.T) {
|
||||
if !bytes.Equal(bufr.Pointer().Bytes(), buf.Pointer().Bytes()) {
|
||||
t.Fatal("unexpected")
|
||||
}
|
||||
bufr.Destroy()
|
||||
bufr.ManualDestroy()
|
||||
|
||||
bufcp = bufcp.Trans()
|
||||
if bufcp.Pointer().Len() != 4096 {
|
||||
@@ -51,7 +51,7 @@ func testBuffer(buf *orbyte.Item[bytes.Buffer], t *testing.T) {
|
||||
if !bytes.Equal(bufcp.Pointer().Bytes(), buf.Pointer().Bytes()) {
|
||||
t.Fatal("unexpected")
|
||||
}
|
||||
bufcp.Destroy()
|
||||
bufcp.ManualDestroy()
|
||||
|
||||
runtime.GC()
|
||||
runtime.Gosched()
|
||||
|
||||
@@ -117,8 +117,3 @@ func (b Bytes) Slice(from, to int) Bytes {
|
||||
nb.dat = b.dat[from:to]
|
||||
return nb
|
||||
}
|
||||
|
||||
// Destroy please refer to Item.Destroy().
|
||||
func (b Bytes) Destroy() {
|
||||
b.buf.Destroy()
|
||||
}
|
||||
|
||||
@@ -11,6 +11,13 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// manualDestroy please refer to Item.manualDestroy().
|
||||
//
|
||||
// Only for test purposes.
|
||||
func (b Bytes) manualDestroy() {
|
||||
b.buf.ManualDestroy()
|
||||
}
|
||||
|
||||
// TestBytesSlice sometimes fails at first run because
|
||||
// GC not collecting all unused items.
|
||||
func TestBytesSlice(t *testing.T) {
|
||||
@@ -29,7 +36,7 @@ func TestBytesSlice(t *testing.T) {
|
||||
t.Log("got:", hex.EncodeToString(x.Bytes()))
|
||||
t.Fatal("index", i, "unexpected")
|
||||
}
|
||||
x.Destroy()
|
||||
x.manualDestroy()
|
||||
// test trans slice
|
||||
b = b.Trans().SliceFrom(5).SliceTo(i - 5 - 5)
|
||||
if !bytes.Equal(buf[5:i-5], b.Bytes()) {
|
||||
@@ -37,7 +44,7 @@ func TestBytesSlice(t *testing.T) {
|
||||
t.Log("got:", hex.EncodeToString(b.Bytes()))
|
||||
t.Fatal("index", i, "unexpected")
|
||||
}
|
||||
b.Destroy()
|
||||
b.manualDestroy()
|
||||
}
|
||||
runtime.GC()
|
||||
runtime.Gosched()
|
||||
@@ -61,7 +68,7 @@ func TestBytesInvolve(t *testing.T) {
|
||||
if !bytes.Equal(b.Bytes(), buf[:i]) {
|
||||
t.Fatal("index", i, "unexpected")
|
||||
}
|
||||
b.Destroy()
|
||||
b.manualDestroy()
|
||||
}
|
||||
runtime.GC()
|
||||
out, in := bufferPool.p.CountItems()
|
||||
@@ -82,7 +89,7 @@ func TestBytesParse(t *testing.T) {
|
||||
if !bytes.Equal(b.Bytes(), buf[:i]) {
|
||||
t.Fatal("index", i, "unexpected")
|
||||
}
|
||||
b.Destroy()
|
||||
b.manualDestroy()
|
||||
}
|
||||
runtime.GC()
|
||||
out, in := bufferPool.p.CountItems()
|
||||
@@ -106,7 +113,7 @@ func TestBytesCopy(t *testing.T) {
|
||||
if bytes.Equal(b.Bytes(), buf[:i]) {
|
||||
t.Fatal("index", i, "unexpected")
|
||||
}
|
||||
b.Destroy()
|
||||
b.manualDestroy()
|
||||
}
|
||||
runtime.GC()
|
||||
out, in := bufferPool.p.CountItems()
|
||||
@@ -134,7 +141,7 @@ func TestBytesTransMultithread(t *testing.T) {
|
||||
if !bytes.Equal(refer, buf.Bytes()) {
|
||||
panic("unexpected")
|
||||
}
|
||||
buf.Destroy()
|
||||
buf.manualDestroy()
|
||||
}(buf.Trans())
|
||||
}()
|
||||
}
|
||||
|
||||
25
pool.go
25
pool.go
@@ -13,7 +13,8 @@ type Pool[T any] struct {
|
||||
pool sync.Pool
|
||||
countin int32
|
||||
countout int32
|
||||
isstrict bool
|
||||
noputbak bool
|
||||
manudstr bool
|
||||
}
|
||||
|
||||
// NewPool make a new pool from custom pooler.
|
||||
@@ -26,11 +27,17 @@ func NewPool[T any](pooler Pooler[T]) *Pool[T] {
|
||||
return p
|
||||
}
|
||||
|
||||
// SetStrictMode panic on every misuse.
|
||||
// SetNoPutBack make it panic on every use-after-destroy.
|
||||
//
|
||||
// Enable this to detect coding errors.
|
||||
func (pool *Pool[T]) SetStrictMode(on bool) {
|
||||
pool.isstrict = on
|
||||
func (pool *Pool[T]) SetNoPutBack(on bool) {
|
||||
pool.noputbak = on
|
||||
}
|
||||
|
||||
// SetManualDestroy mark that user must manually
|
||||
// run Item.Destroy().
|
||||
func (pool *Pool[T]) SetManualDestroy(on bool) {
|
||||
pool.manudstr = on
|
||||
}
|
||||
|
||||
func (pool *Pool[T]) incin() {
|
||||
@@ -56,17 +63,21 @@ func (pool *Pool[T]) newempty() *Item[T] {
|
||||
}
|
||||
item.stat = status(0)
|
||||
pool.incout()
|
||||
item.setautodestroy()
|
||||
if !pool.manudstr {
|
||||
item.setautodestroy()
|
||||
}
|
||||
return item
|
||||
}
|
||||
|
||||
func (pool *Pool[T]) put(item *Item[T]) {
|
||||
runtime.SetFinalizer(item, nil)
|
||||
if !pool.manudstr {
|
||||
runtime.SetFinalizer(item, nil)
|
||||
}
|
||||
|
||||
item.stat.setdestroyed(true)
|
||||
item.cfg = nil
|
||||
|
||||
if pool.isstrict {
|
||||
if pool.noputbak {
|
||||
return
|
||||
}
|
||||
pool.pool.Put(item)
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
func TestPool(t *testing.T) {
|
||||
p := NewPool[[]byte](simplepooler{})
|
||||
x := p.New(200)
|
||||
x.Destroy()
|
||||
x.ManualDestroy()
|
||||
out, in := p.CountItems()
|
||||
t.Log("out", out, "in", in)
|
||||
if out != 0 || in != 1 {
|
||||
@@ -22,7 +22,7 @@ func TestPool(t *testing.T) {
|
||||
if out != 1 || in != 0 {
|
||||
t.Fatal("unexpected behavior")
|
||||
}
|
||||
item.Destroy()
|
||||
item.ManualDestroy()
|
||||
}
|
||||
out, in = p.CountItems()
|
||||
t.Log("out", out, "in", in)
|
||||
@@ -53,7 +53,7 @@ func TestPool(t *testing.T) {
|
||||
func user(item *Item[[]byte], wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
rand.Read(item.Unwrap())
|
||||
item.Destroy()
|
||||
item.ManualDestroy()
|
||||
}
|
||||
|
||||
func usernodestroy(item *Item[[]byte], wg *sync.WaitGroup) {
|
||||
|
||||
Reference in New Issue
Block a user