]> 127.0.0.1 Git - part/.git/commitdiff
pool,slice
authorqydysky <32743305+qydysky@users.noreply.github.com>
Wed, 18 Jan 2023 07:44:05 +0000 (15:44 +0800)
committerqydysky <32743305+qydysky@users.noreply.github.com>
Wed, 18 Jan 2023 07:44:05 +0000 (15:44 +0800)
pool/Pool.go [new file with mode: 0644]
pool/Pool_test.go [new file with mode: 0644]
slice/Slice.go [new file with mode: 0644]
slice/Slice_test.go [new file with mode: 0644]

diff --git a/pool/Pool.go b/pool/Pool.go
new file mode 100644 (file)
index 0000000..c025df6
--- /dev/null
@@ -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 (file)
index 0000000..96ed4f2
--- /dev/null
@@ -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 (file)
index 0000000..b6a42da
--- /dev/null
@@ -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 (file)
index 0000000..b5df02b
--- /dev/null
@@ -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()
+       }
+}