diff options
Diffstat (limited to 'vendor/codeberg.org/gruf/go-structr/queue.go')
-rw-r--r-- | vendor/codeberg.org/gruf/go-structr/queue.go | 342 |
1 files changed, 0 insertions, 342 deletions
diff --git a/vendor/codeberg.org/gruf/go-structr/queue.go b/vendor/codeberg.org/gruf/go-structr/queue.go deleted file mode 100644 index dab925f95..000000000 --- a/vendor/codeberg.org/gruf/go-structr/queue.go +++ /dev/null @@ -1,342 +0,0 @@ -package structr - -import ( - "reflect" - "sync" - "unsafe" -) - -// QueueConfig defines config vars -// for initializing a struct queue. -type QueueConfig[StructType any] struct { - - // Pop is called when queue values - // are popped, during calls to any - // of the Pop___() series of fns. - Pop func(StructType) - - // Indices defines indices to create - // in the Queue for the receiving - // generic struct parameter type. - Indices []IndexConfig -} - -// Queue provides a structure model queue with -// automated indexing and popping by any init -// defined lookups of field combinations. -type Queue[StructType any] struct { - - // hook functions. - copy func(StructType) StructType - pop func(StructType) - - // main underlying - // struct item queue. - queue list - - // indices used in storing passed struct - // types by user defined sets of fields. - indices []Index - - // protective mutex, guards: - // - Queue{}.queue - // - Index{}.data - // - Queue{} hook fns - mutex sync.Mutex -} - -// Init initializes the queue with given configuration -// including struct fields to index, and necessary fns. -func (q *Queue[T]) Init(config QueueConfig[T]) { - t := reflect.TypeOf((*T)(nil)).Elem() - - if len(config.Indices) == 0 { - panic("no indices provided") - } - - // Safely copy over - // provided config. - q.mutex.Lock() - q.indices = make([]Index, len(config.Indices)) - for i, cfg := range config.Indices { - q.indices[i].ptr = unsafe.Pointer(q) - q.indices[i].init(t, cfg, 0) - } - q.pop = config.Pop - q.mutex.Unlock() -} - -// Index selects index with given name from queue, else panics. -func (q *Queue[T]) Index(name string) *Index { - for i, idx := range q.indices { - if idx.name == name { - return &(q.indices[i]) - } - } - panic("unknown index: " + name) -} - -// PopFront pops the current value at front of the queue. -func (q *Queue[T]) PopFront() (T, bool) { - t := q.PopFrontN(1) - if len(t) == 0 { - var t T - return t, false - } - return t[0], true -} - -// PopBack pops the current value at back of the queue. -func (q *Queue[T]) PopBack() (T, bool) { - t := q.PopBackN(1) - if len(t) == 0 { - var t T - return t, false - } - return t[0], true -} - -// PopFrontN attempts to pop n values from front of the queue. -func (q *Queue[T]) PopFrontN(n int) []T { - return q.pop_n(n, func() *list_elem { - return q.queue.head - }) -} - -// PopBackN attempts to pop n values from back of the queue. -func (q *Queue[T]) PopBackN(n int) []T { - return q.pop_n(n, func() *list_elem { - return q.queue.tail - }) -} - -// Pop attempts to pop values from queue indexed under any of keys. -func (q *Queue[T]) Pop(index *Index, keys ...Key) []T { - if index == nil { - panic("no index given") - } else if index.ptr != unsafe.Pointer(q) { - panic("invalid index for queue") - } - - // Acquire lock. - q.mutex.Lock() - - // Preallocate expected ret slice. - values := make([]T, 0, len(keys)) - - for i := range keys { - // Delete all items under key from index, collecting - // value items and dropping them from all their indices. - index.delete(keys[i].key, func(item *indexed_item) { - - // Append deleted to values. - value := item.data.(T) - values = append(values, value) - - // Delete queued. - q.delete(item) - }) - } - - // Get func ptrs. - pop := q.pop - - // Done with lock. - q.mutex.Unlock() - - if pop != nil { - // Pass all popped values - // to given user hook (if set). - for _, value := range values { - pop(value) - } - } - - return values -} - -// PushFront pushes values to front of queue. -func (q *Queue[T]) PushFront(values ...T) { - q.mutex.Lock() - for i := range values { - item := q.index(values[i]) - q.queue.push_front(&item.elem) - } - q.mutex.Unlock() -} - -// PushBack pushes values to back of queue. -func (q *Queue[T]) PushBack(values ...T) { - q.mutex.Lock() - for i := range values { - item := q.index(values[i]) - q.queue.push_back(&item.elem) - } - q.mutex.Unlock() -} - -// MoveFront attempts to move values indexed under any of keys to the front of the queue. -func (q *Queue[T]) MoveFront(index *Index, keys ...Key) { - q.mutex.Lock() - for i := range keys { - index.get(keys[i].key, func(item *indexed_item) { - q.queue.move_front(&item.elem) - }) - } - q.mutex.Unlock() -} - -// MoveBack attempts to move values indexed under any of keys to the back of the queue. -func (q *Queue[T]) MoveBack(index *Index, keys ...Key) { - q.mutex.Lock() - for i := range keys { - index.get(keys[i].key, func(item *indexed_item) { - q.queue.move_back(&item.elem) - }) - } - q.mutex.Unlock() -} - -// Len returns the current length of queue. -func (q *Queue[T]) Len() int { - q.mutex.Lock() - l := q.queue.len - q.mutex.Unlock() - return l -} - -// Debug returns debug stats about queue. -func (q *Queue[T]) Debug() map[string]any { - m := make(map[string]any, 2) - q.mutex.Lock() - m["queue"] = q.queue.len - indices := make(map[string]any, len(q.indices)) - m["indices"] = indices - for _, idx := range q.indices { - var n uint64 - for _, l := range idx.data.m { - n += uint64(l.len) - } - indices[idx.name] = n - } - q.mutex.Unlock() - return m -} - -func (q *Queue[T]) pop_n(n int, next func() *list_elem) []T { - if next == nil { - panic("nil fn") - } - - // Acquire lock. - q.mutex.Lock() - - // Preallocate ret slice. - values := make([]T, 0, n) - - // Iterate over 'n' items. - for i := 0; i < n; i++ { - - // Get next elem. - next := next() - if next == nil { - - // reached - // end. - break - } - - // Cast the indexed item from elem. - item := (*indexed_item)(next.data) - - // Append deleted to values. - value := item.data.(T) - values = append(values, value) - - // Delete queued. - q.delete(item) - } - - // Get func ptrs. - pop := q.pop - - // Done with lock. - q.mutex.Unlock() - - if pop != nil { - // Pass all popped values - // to given user hook (if set). - for _, value := range values { - pop(value) - } - } - - return values -} - -func (q *Queue[T]) index(value T) *indexed_item { - item := new_indexed_item() - if cap(item.indexed) < len(q.indices) { - - // Preallocate item indices slice to prevent Go auto - // allocating overlying large slices we don't need. - item.indexed = make([]*index_entry, 0, len(q.indices)) - } - - // Set item value. - item.data = value - - // Get ptr to value data. - ptr := unsafe.Pointer(&value) - - // Acquire key buf. - buf := new_buffer() - - for i := range q.indices { - // Get current index ptr. - idx := &(q.indices[i]) - - // Extract fields comprising index key. - parts := extract_fields(ptr, idx.fields) - if parts == nil { - continue - } - - // Calculate index key. - key := idx.key(buf, parts) - if key == "" { - continue - } - - // Append item to this index. - idx.append(&q.queue, key, item) - } - - // Done with buf. - free_buffer(buf) - - return item -} - -func (q *Queue[T]) delete(item *indexed_item) { - for len(item.indexed) != 0 { - // Pop last indexed entry from list. - entry := item.indexed[len(item.indexed)-1] - item.indexed = item.indexed[:len(item.indexed)-1] - - // Get entry's index. - index := entry.index - - // Drop this index_entry. - index.delete_entry(entry) - - // Check compact map. - index.data.Compact() - } - - // Drop entry from queue list. - q.queue.remove(&item.elem) - - // Free now-unused item. - free_indexed_item(item) -} |