204 lines
3.1 KiB
Go
204 lines
3.1 KiB
Go
package lfu
|
|
|
|
import (
|
|
"sync/atomic"
|
|
)
|
|
|
|
type List[T any] struct {
|
|
root *Element[T]
|
|
len atomic.Int32
|
|
sync *Synchronizer[*Element[T]]
|
|
}
|
|
|
|
func (l *List[T]) First() *Element[T] {
|
|
if l.Len() == 0 {
|
|
return nil
|
|
}
|
|
|
|
var next *Element[T]
|
|
l.sync.ReadTx(l.root, func(upgrade func(func())) error {
|
|
next = l.root.next
|
|
return nil
|
|
})
|
|
|
|
return next
|
|
}
|
|
|
|
func (l *List[T]) Last() *Element[T] {
|
|
if l.Len() == 0 {
|
|
return nil
|
|
}
|
|
|
|
var prev *Element[T]
|
|
l.sync.ReadTx(l.root, func(upgrade func(func())) error {
|
|
prev = l.root.prev
|
|
return nil
|
|
})
|
|
|
|
return prev
|
|
}
|
|
|
|
func (l *List[T]) Prev(e *Element[T]) *Element[T] {
|
|
var prev *Element[T]
|
|
l.sync.ReadTx(e, func(upgrade func(func())) error {
|
|
prev = e.prev
|
|
return nil
|
|
})
|
|
|
|
return prev
|
|
}
|
|
|
|
func (l *List[T]) Next(e *Element[T]) *Element[T] {
|
|
var next *Element[T]
|
|
l.sync.ReadTx(e, func(upgrade func(func())) error {
|
|
next = e.next
|
|
return nil
|
|
})
|
|
|
|
return next
|
|
}
|
|
|
|
func (l *List[T]) Value(e *Element[T]) T {
|
|
var value T
|
|
l.sync.ReadTx(e, func(upgrade func(func())) error {
|
|
value = e.value
|
|
return nil
|
|
})
|
|
|
|
return value
|
|
}
|
|
|
|
func (l *List[T]) PushFront(v T) *Element[T] {
|
|
return l.InsertValueAfter(v, l.root)
|
|
}
|
|
|
|
func (l *List[T]) PushBack(v T) *Element[T] {
|
|
return l.InsertValueAfter(v, l.root)
|
|
}
|
|
|
|
func (l *List[T]) Remove(e *Element[T]) {
|
|
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] {
|
|
l.sync.ReadTx(e, func(upgrade func(fn func())) error {
|
|
var next *Element[T]
|
|
l.sync.ReadTx(at, func(upgrade func(func())) error {
|
|
next = at.next
|
|
return nil
|
|
})
|
|
|
|
upgrade(func() {
|
|
e.prev = at
|
|
e.next = next
|
|
e.list = l
|
|
})
|
|
|
|
if e.prev != nil {
|
|
l.sync.WriteTx(e.prev, func() error {
|
|
e.prev.next = e
|
|
return nil
|
|
})
|
|
}
|
|
|
|
if e.next != nil {
|
|
l.sync.WriteTx(e.next, func() error {
|
|
e.next.prev = e
|
|
return nil
|
|
})
|
|
}
|
|
|
|
return nil
|
|
})
|
|
|
|
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]) {
|
|
if e == nil && e == l.root {
|
|
return
|
|
}
|
|
|
|
l.sync.ReadTx(e, func(upgrade func(fn func())) error {
|
|
if e.prev != nil {
|
|
if e.prev == e {
|
|
upgrade(func() {
|
|
e.prev.next = e.next
|
|
})
|
|
} else {
|
|
l.sync.WriteTx(e.prev, func() error {
|
|
e.prev.next = e.next
|
|
return nil
|
|
})
|
|
}
|
|
}
|
|
|
|
if e.next != nil {
|
|
if e.next == e {
|
|
upgrade(func() {
|
|
e.next.prev = e.prev
|
|
})
|
|
} else {
|
|
l.sync.WriteTx(e.next, func() error {
|
|
e.next.prev = e.prev
|
|
return nil
|
|
})
|
|
}
|
|
}
|
|
|
|
upgrade(func() {
|
|
e.next = nil
|
|
e.prev = nil
|
|
e.list = nil
|
|
})
|
|
|
|
return nil
|
|
})
|
|
|
|
l.sync.Remove(e)
|
|
l.len.Add(-1)
|
|
}
|
|
|
|
func NewList[T any]() *List[T] {
|
|
root := NewElement(*new(T))
|
|
root.next = root
|
|
root.prev = root
|
|
|
|
list := &List[T]{
|
|
sync: NewSynchronizer[*Element[T]](),
|
|
}
|
|
|
|
root.list = list
|
|
list.root = root
|
|
|
|
return list
|
|
}
|
|
|
|
type Element[T any] struct {
|
|
prev *Element[T]
|
|
next *Element[T]
|
|
list *List[T]
|
|
value T
|
|
}
|
|
|
|
func NewElement[T any](v T) *Element[T] {
|
|
element := &Element[T]{
|
|
prev: nil,
|
|
next: nil,
|
|
list: nil,
|
|
value: v,
|
|
}
|
|
return element
|
|
}
|