From 8c21b29bfd0b556ef79463a5ba0db6e63727d42d Mon Sep 17 00:00:00 2001 From: Annika Hannig Date: Tue, 15 Nov 2022 10:32:14 +0100 Subject: [PATCH] added int list pool --- pkg/store/pools/int_list.go | 83 ++++++++++++++++++++++++++------ pkg/store/pools/int_list_test.go | 26 ++++++++++ 2 files changed, 93 insertions(+), 16 deletions(-) create mode 100644 pkg/store/pools/int_list_test.go diff --git a/pkg/store/pools/int_list.go b/pkg/store/pools/int_list.go index 586917d..fed5175 100644 --- a/pkg/store/pools/int_list.go +++ b/pkg/store/pools/int_list.go @@ -1,33 +1,72 @@ package pools -import "sync" +import ( + "sync" +) // IntNode is a node in the tree. type IntNode struct { children []*IntNode value int - ptr any + counter int + ptr []int +} + +// Internally acquire list by traversing the tree and +// creating nodes if required. +func (n *IntNode) traverse(list, tail []int) []int { + head := tail[0] + tail = tail[1:] + + // Seek for value in children + var child *IntNode + for _, c := range n.children { + if c.value == head { + child = c + } + } + if child == nil { + // Insert child + child = &IntNode{ + children: []*IntNode{}, + value: head, + ptr: nil, + } + n.children = append(n.children, child) + } + + // Set list ptr if required + if len(tail) == 0 { + if child.ptr == nil { + child.ptr = list + } + return child.ptr + } + + return child.traverse(list, tail) } // IntTree is a tree structure for deduplicating // lists of integers. type IntTree struct { - children []*IntNode + root *IntNode } -// Acquire int list +// NewIntTree initializes an empty int tree +func NewIntTree() *IntTree { + return &IntTree{ + root: &IntNode{ + ptr: []int{}, + }, + } +} + +// Acquire int list element func (t *IntTree) Acquire(list []int) []int { if len(list) == 0 { - return nil - } - v := list[0] - var node *IntNode - // TODO - for _, c := range t.children { - if c.value == v { - // TODO - } + return t.root.ptr // root } + return t.root.traverse(list, list) } // A IntList pool can be used to deduplicate @@ -35,8 +74,20 @@ func (t *IntTree) Acquire(list []int) []int { // // A Tree datastructure is used. type IntList struct { - values *IntTree - counter *IntTree - + values *IntTree sync.Mutex } + +// NewIntList creates a new int list pool +func NewIntList() *IntList { + return &IntList{ + values: NewIntTree(), + } +} + +// Acquire int list from pool +func (p *IntList) Acquire(list []int) []int { + p.Lock() + defer p.Unlock() + return p.values.Acquire(list) +} diff --git a/pkg/store/pools/int_list_test.go b/pkg/store/pools/int_list_test.go new file mode 100644 index 0000000..ef28a24 --- /dev/null +++ b/pkg/store/pools/int_list_test.go @@ -0,0 +1,26 @@ +package pools + +import ( + "fmt" + "testing" +) + +func TestAcquireIntList(t *testing.T) { + a := []int{23, 42, 1337, 65535, 1} + b := []int{23, 42, 1337, 65535, 1} + c := []int{23, 42, 1338, 65535, 2} + + p := NewIntList() + + r1 := p.Acquire(a) + p.Acquire(c) + r2 := p.Acquire(b) + + if fmt.Sprintf("%p", a) == fmt.Sprintf("%p", b) { + t.Error("lists should not be same pointer", fmt.Sprintf("%p %p", a, b)) + } + if fmt.Sprintf("%p", r1) != fmt.Sprintf("%p", r2) { + t.Error("lists should be same pointer", fmt.Sprintf("%p %p", r1, r2)) + } + t.Log(fmt.Sprintf("Ptr: %p %p => %p %p", a, b, r1, r2)) +}