summaryrefslogtreecommitdiff
path: root/vendor/codeberg.org/gruf/go-mempool/simple.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/codeberg.org/gruf/go-mempool/simple.go')
-rw-r--r--vendor/codeberg.org/gruf/go-mempool/simple.go111
1 files changed, 111 insertions, 0 deletions
diff --git a/vendor/codeberg.org/gruf/go-mempool/simple.go b/vendor/codeberg.org/gruf/go-mempool/simple.go
new file mode 100644
index 000000000..c9f459890
--- /dev/null
+++ b/vendor/codeberg.org/gruf/go-mempool/simple.go
@@ -0,0 +1,111 @@
+package mempool
+
+import (
+ "unsafe"
+)
+
+// SimplePool provides a type-safe form
+// of UnsafePool using generics.
+//
+// Note it is NOT safe for concurrent
+// use, you must protect it yourself!
+type SimplePool[T any] struct {
+ UnsafeSimplePool
+
+ // New is an optionally provided
+ // allocator used when no value
+ // is available for use in pool.
+ New func() T
+
+ // Reset is an optionally provided
+ // value resetting function called
+ // on passed value to Put().
+ Reset func(T) bool
+}
+
+func (p *SimplePool[T]) Get() T {
+ if ptr := p.UnsafeSimplePool.Get(); ptr != nil {
+ return *(*T)(ptr)
+ }
+ var t T
+ if p.New != nil {
+ t = p.New()
+ }
+ return t
+}
+
+func (p *SimplePool[T]) Put(t T) {
+ if p.Reset != nil && !p.Reset(t) {
+ return
+ }
+ ptr := unsafe.Pointer(&t)
+ p.UnsafeSimplePool.Put(ptr)
+}
+
+// UnsafeSimplePool provides an incredibly
+// simple memory pool implementation
+// that stores ptrs to memory values,
+// and regularly flushes internal pool
+// structures according to CheckGC().
+//
+// Note it is NOT safe for concurrent
+// use, you must protect it yourself!
+type UnsafeSimplePool struct {
+
+ // Check determines how often to flush
+ // internal pools based on underlying
+ // current and victim pool sizes. It gets
+ // called on every pool Put() operation.
+ //
+ // A flush will start a new current
+ // pool, make victim the old current,
+ // and drop the existing victim pool.
+ Check func(current, victim int) bool
+
+ current []unsafe.Pointer
+ victim []unsafe.Pointer
+}
+
+func (p *UnsafeSimplePool) Get() unsafe.Pointer {
+ // First try current list.
+ if len(p.current) > 0 {
+ ptr := p.current[len(p.current)-1]
+ p.current = p.current[:len(p.current)-1]
+ return ptr
+ }
+
+ // Fallback to victim.
+ if len(p.victim) > 0 {
+ ptr := p.victim[len(p.victim)-1]
+ p.victim = p.victim[:len(p.victim)-1]
+ return ptr
+ }
+
+ return nil
+}
+
+func (p *UnsafeSimplePool) Put(ptr unsafe.Pointer) {
+ p.current = append(p.current, ptr)
+
+ // Get GC check func.
+ if p.Check == nil {
+ p.Check = defaultCheck
+ }
+
+ if p.Check(len(p.current), len(p.victim)) {
+ p.GC() // garbage collection time!
+ }
+}
+
+func (p *UnsafeSimplePool) GC() {
+ p.victim = p.current
+ p.current = nil
+}
+
+func (p *UnsafeSimplePool) Size() int {
+ return len(p.current) + len(p.victim)
+}
+
+func defaultCheck(current, victim int) bool {
+ return current-victim > 128 || victim > 256
+}