From 36b904cd4552d7a1755741a204f172aace9f0066 Mon Sep 17 00:00:00 2001 From: qydysky <32743305+qydysky@users.noreply.github.com> Date: Wed, 18 Jan 2023 15:44:05 +0800 Subject: [PATCH] pool,slice --- pool/Pool.go | 73 +++++++++++++++++++ pool/Pool_test.go | 52 ++++++++++++++ slice/Slice.go | 167 ++++++++++++++++++++++++++++++++++++++++++++ slice/Slice_test.go | 52 ++++++++++++++ 4 files changed, 344 insertions(+) create mode 100644 pool/Pool.go create mode 100644 pool/Pool_test.go create mode 100644 slice/Slice.go create mode 100644 slice/Slice_test.go diff --git a/pool/Pool.go b/pool/Pool.go new file mode 100644 index 0000000..c025df6 --- /dev/null +++ b/pool/Pool.go @@ -0,0 +1,73 @@ +package part + +import ( + "sync" +) + +type buf[T any] struct { + maxsize int + newF func() *T + validF func(*T) bool + reuseF func(*T) *T + buf []*T + sync.RWMutex +} + +func New[T any](NewF func() *T, ValidF func(*T) bool, ReuseF func(*T) *T, maxsize int) *buf[T] { + t := new(buf[T]) + t.newF = NewF + t.validF = ValidF + t.reuseF = ReuseF + t.maxsize = maxsize + return t +} + +func (t *buf[T]) Trim() { + t.Lock() + defer t.Unlock() + + for i := 0; i < len(t.buf); i++ { + if !t.validF(t.buf[i]) { + t.buf[i] = nil + t.buf = append(t.buf[:i], t.buf[i:]...) + i-- + } + } +} + +func (t *buf[T]) Get() *T { + t.Lock() + defer t.Unlock() + + for i := 0; i < len(t.buf); i++ { + if !t.validF(t.buf[i]) { + return t.reuseF(t.buf[i]) + } + } + + return t.newF() +} + +func (t *buf[T]) Put(item ...*T) { + if len(item) == 0 { + return + } + + t.Lock() + defer t.Unlock() + + var cu = 0 + for i := 0; i < len(t.buf); i++ { + if !t.validF(t.buf[i]) { + t.buf[i] = item[cu] + cu++ + if cu >= len(item) { + return + } + } + } + + for i := cu; i < len(item) && t.maxsize > len(t.buf); i++ { + t.buf = append(t.buf, item[i]) + } +} diff --git a/pool/Pool_test.go b/pool/Pool_test.go new file mode 100644 index 0000000..96ed4f2 --- /dev/null +++ b/pool/Pool_test.go @@ -0,0 +1,52 @@ +package part + +import ( + "testing" + "unsafe" +) + +type a struct { + d []byte + v bool +} + +func TestXxx(t *testing.T) { + var newf = func() *a { + return &a{v: true} + } + + var validf = func(t *a) bool { + return t.v + } + + var reusef = func(t *a) *a { + t.d = t.d[:0] + t.v = true + return t + } + + var b = New(newf, validf, reusef, 10) + + var c1 = b.Get() + c1.d = append(c1.d, []byte("1")...) + + t.Log(unsafe.Pointer(c1), c1) + + var c2 = b.Get() + c2.d = append(c2.d, []byte("2")...) + + t.Log(unsafe.Pointer(c2), c2) + + b.Put(c1) + + t.Log(unsafe.Pointer(c1), c1) + + c1.v = false + + t.Log(unsafe.Pointer(c1), c1) + + var c3 = b.Get() + + t.Log(unsafe.Pointer(c3), c3) + +} diff --git a/slice/Slice.go b/slice/Slice.go new file mode 100644 index 0000000..b6a42da --- /dev/null +++ b/slice/Slice.go @@ -0,0 +1,167 @@ +package part + +import ( + "errors" + "sync" + "unsafe" +) + +type buf[T any] struct { + maxsize int + bufsize int + modified Modified + buf []T + sync.RWMutex +} + +type Modified struct { + p uintptr + t uint64 +} + +func New[T any](maxsize ...int) *buf[T] { + t := new(buf[T]) + if len(maxsize) > 0 { + t.maxsize = maxsize[0] + } + t.modified.p = uintptr(unsafe.Pointer(t)) + return t +} + +func (t *buf[T]) Clear() { + t.Lock() + defer t.Unlock() + t.buf = nil + t.bufsize = 0 + t.modified.t += 1 +} + +func (t *buf[T]) Size() int { + t.RLock() + defer t.RUnlock() + + return t.bufsize +} + +func (t *buf[T]) IsEmpty() bool { + t.RLock() + defer t.RUnlock() + + return t.bufsize == 0 +} + +func (t *buf[T]) Reset() { + t.Lock() + defer t.Unlock() + + t.bufsize = 0 + t.modified.t += 1 +} + +func (t *buf[T]) Append(data []T) error { + t.Lock() + defer t.Unlock() + + if len(t.buf)+len(data) > t.maxsize { + return errors.New("超出设定maxsize") + } else if len(t.buf) == 0 { + if t.maxsize == 0 { + t.buf = make([]T, len(data)) + } else { + t.buf = make([]T, len(data), t.maxsize) + } + } else { + diff := len(t.buf) - t.bufsize - len(data) + if diff < 0 { + t.buf = append(t.buf, make([]T, -diff)...) + } else { + t.buf = t.buf[:t.bufsize+len(data)] + } + } + t.bufsize += copy(t.buf[t.bufsize:], data) + t.modified.t += 1 + return nil +} + +func (t *buf[T]) RemoveFront(n int) error { + if n <= 0 { + return nil + } + + t.Lock() + defer t.Unlock() + + if t.bufsize < n { + return errors.New("尝试移除的数值大于长度") + } else if t.bufsize == n { + t.bufsize = 0 + } else { + t.bufsize = copy(t.buf, t.buf[n:t.bufsize]) + } + + t.modified.t += 1 + return nil +} + +func (t *buf[T]) RemoveBack(n int) error { + if n <= 0 { + return nil + } + + t.Lock() + defer t.Unlock() + + if t.bufsize < n { + return errors.New("尝试移除的数值大于长度") + } else if t.bufsize == n { + t.bufsize = 0 + } else { + t.bufsize -= n + } + + t.modified.t += 1 + return nil +} + +// unsafe +func (t *buf[T]) SetModified() { + t.Lock() + defer t.Unlock() + + t.modified.t += 1 +} + +func (t *buf[T]) GetModified() Modified { + t.RLock() + defer t.RUnlock() + + return t.modified +} + +func (t *buf[T]) HadModified(mt Modified) (same bool, err error) { + t.RLock() + defer t.RUnlock() + + if t.modified.p != mt.p { + err = errors.New("不能对比不同buf") + } + same = t.modified.t != mt.t + return +} + +// unsafe +func (t *buf[T]) GetPureBuf() (buf []T) { + t.RLock() + defer t.RUnlock() + + return t.buf[:t.bufsize] +} + +func (t *buf[T]) GetCopyBuf() (buf []T) { + t.RLock() + defer t.RUnlock() + + buf = make([]T, t.bufsize) + copy(buf, t.buf[:t.bufsize]) + return +} diff --git a/slice/Slice_test.go b/slice/Slice_test.go new file mode 100644 index 0000000..b5df02b --- /dev/null +++ b/slice/Slice_test.go @@ -0,0 +1,52 @@ +package part + +import ( + "bytes" + "testing" +) + +func TestXxx(t *testing.T) { + var ( + b = New[byte](5) + c = New[byte]() + ) + if !b.IsEmpty() { + t.Fatal() + } + b.Append([]byte("abc")) + if b.IsEmpty() || b.Size() != 3 { + t.Fatal() + } + if _, e := b.HadModified(c.GetModified()); e == nil { + t.Fatal() + } + bc := b.GetCopyBuf() + bt := b.GetModified() + b.RemoveFront(1) + if b.IsEmpty() || b.Size() != 2 || !bytes.Equal(bc, []byte("abc")) || + !bytes.Equal(b.GetPureBuf(), []byte("bc")) || bt == b.GetModified() { + t.Fatal() + } + b.RemoveBack(1) + if b.IsEmpty() || b.Size() != 1 || !bytes.Equal(bc, []byte("abc")) || !bytes.Equal(b.GetPureBuf(), []byte("b")) { + t.Fatal() + } + b.Reset() + if !b.IsEmpty() || b.Size() != 0 || !bytes.Equal(bc, []byte("abc")) || !bytes.Equal(b.GetPureBuf(), []byte("")) { + t.Fatal() + } + if e := b.RemoveFront(1); e == nil || e.Error() != "尝试移除的数值大于长度" { + t.Fatal() + } + if e := b.Append([]byte("abcdef")); e == nil || e.Error() != "超出设定maxsize" { + t.Fatal() + } + b.Clear() + if !b.IsEmpty() || b.Size() != 0 { + t.Fatal() + } + b.Append([]byte("abc")) + if b.IsEmpty() || b.Size() != 3 { + t.Fatal() + } +} -- 2.39.2