163 lines
2.5 KiB
Go
163 lines
2.5 KiB
Go
|
package lfu
|
||
|
|
||
|
import (
|
||
|
"sync/atomic"
|
||
|
)
|
||
|
|
||
|
type List[T any] struct {
|
||
|
root atomic.Pointer[Element[T]]
|
||
|
len atomic.Int32
|
||
|
}
|
||
|
|
||
|
func (l *List[T]) First() *Element[T] {
|
||
|
if l.len.Load() == 0 {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
root := l.root.Load()
|
||
|
|
||
|
return root.next.Load()
|
||
|
}
|
||
|
|
||
|
func (l *List[T]) Last() *Element[T] {
|
||
|
if l.len.Load() == 0 {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
root := l.root.Load()
|
||
|
|
||
|
return root.prev.Load()
|
||
|
}
|
||
|
|
||
|
func (l *List[T]) PushFront(v T) *Element[T] {
|
||
|
root := l.root.Load()
|
||
|
return l.InsertValueAfter(v, root)
|
||
|
}
|
||
|
|
||
|
func (l *List[T]) PushBack(v T) *Element[T] {
|
||
|
root := l.root.Load()
|
||
|
return l.InsertValueAfter(v, root)
|
||
|
}
|
||
|
|
||
|
func (l *List[T]) Remove(e *Element[T]) {
|
||
|
if e.list.Load() == l {
|
||
|
l.remove(e)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (l *List[T]) Len() int {
|
||
|
return int(l.len.Load())
|
||
|
}
|
||
|
|
||
|
func (l *List[T]) insertAfter(e *Element[T], at *Element[T]) *Element[T] {
|
||
|
e.prev.Store(at)
|
||
|
e.next.Store(at.next.Load())
|
||
|
|
||
|
prev := e.prev.Load()
|
||
|
if prev != nil {
|
||
|
prev.next.Store(e)
|
||
|
}
|
||
|
|
||
|
next := e.next.Load()
|
||
|
if next != nil {
|
||
|
next.prev.Store(e)
|
||
|
}
|
||
|
|
||
|
e.list.Store(l)
|
||
|
|
||
|
l.len.Add(1)
|
||
|
|
||
|
return e
|
||
|
}
|
||
|
|
||
|
func (l *List[T]) InsertValueAfter(v T, at *Element[T]) *Element[T] {
|
||
|
e := NewElement[T](v)
|
||
|
return l.insertAfter(e, at)
|
||
|
}
|
||
|
|
||
|
func (l *List[T]) remove(e *Element[T]) {
|
||
|
prev := e.prev.Load()
|
||
|
if prev != nil {
|
||
|
prev.next.Store(e.next.Load())
|
||
|
}
|
||
|
|
||
|
next := e.next.Load()
|
||
|
if next != nil {
|
||
|
next.prev.Store(e.prev.Load())
|
||
|
}
|
||
|
|
||
|
e.next.Store(nil)
|
||
|
e.prev.Store(nil)
|
||
|
e.list.Store(nil)
|
||
|
|
||
|
l.len.Add(-1)
|
||
|
}
|
||
|
|
||
|
func NewList[T any]() *List[T] {
|
||
|
root := NewElement(*new(T))
|
||
|
root.next.Store(root)
|
||
|
root.prev.Store(root)
|
||
|
|
||
|
list := &List[T]{}
|
||
|
|
||
|
root.list.Store(list)
|
||
|
atomic := atomic.Pointer[Element[T]]{}
|
||
|
atomic.Store(root)
|
||
|
list.root = atomic
|
||
|
|
||
|
return list
|
||
|
}
|
||
|
|
||
|
type Element[T any] struct {
|
||
|
prev atomic.Pointer[Element[T]]
|
||
|
next atomic.Pointer[Element[T]]
|
||
|
list atomic.Pointer[List[T]]
|
||
|
value atomic.Pointer[T]
|
||
|
}
|
||
|
|
||
|
func (e *Element[T]) Next() *Element[T] {
|
||
|
l := e.list.Load()
|
||
|
if l == nil {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
n := e.next.Load()
|
||
|
r := l.root.Load()
|
||
|
|
||
|
if n == r {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
return n
|
||
|
}
|
||
|
|
||
|
func (e *Element[T]) Prev() *Element[T] {
|
||
|
l := e.list.Load()
|
||
|
if l == nil {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
p := e.prev.Load()
|
||
|
r := l.root.Load()
|
||
|
if p == r {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
return p
|
||
|
}
|
||
|
|
||
|
func (e *Element[T]) Value() T {
|
||
|
return *e.value.Load()
|
||
|
}
|
||
|
|
||
|
func NewElement[T any](v T) *Element[T] {
|
||
|
value := atomic.Pointer[T]{}
|
||
|
value.Store(&v)
|
||
|
return &Element[T]{
|
||
|
value: value,
|
||
|
prev: atomic.Pointer[Element[T]]{},
|
||
|
next: atomic.Pointer[Element[T]]{},
|
||
|
list: atomic.Pointer[List[T]]{},
|
||
|
}
|
||
|
}
|