1
0
mirror of https://github.com/charlienet/go-mixed.git synced 2026-07-14 08:17:26 +08:00
Files
go-mixed/collections/linked_list.go
T
Charlie c44a325384 fix: 修复多处并发安全问题及锁实现重构
locker: 导出 RWLocker/EmptyLocker 接口, 新增 WithRWLocker, 重构
  SourceLocker 竞态、Synchronize 数据竞态

collections/linked_list: 补齐 ForEach/Size/GetAt/RemoveAt/ToList
  等方法的锁保护
collections/queue,stack: Peek/Size/IsEmpty 加锁
collections/list/linked_list: Front/Back/GetAt 加锁
maps: rwlock_map.Exist/Count, hash_map.Count 加锁
delay_queue/mem_store: Pop 原子化、Len/IsEmpty 加锁
cleanup_guard: Run() 检查 enable 标志
sets/ketama: 修复接口变更导致的 nil 空指针
2026-06-05 10:45:08 +08:00

232 lines
3.5 KiB
Go

package collections
import (
"fmt"
"github.com/charlienet/go-mixed/locker"
)
// 单链表节点
type linkedNode[T any] struct {
item T
next *linkedNode[T]
}
// 双向链接节点
type doubleLinkedNode[T any] struct {
item T
prev *linkedNode[T]
next *linkedNode[T]
}
type LinkedList[T any] struct {
mu locker.RWLocker
head, tail *linkedNode[T]
size int
}
// 初始化单向链表
func NewLinkedList[T any](vals ...T) *LinkedList[T] {
l := &LinkedList[T]{mu: locker.EmptyLocker}
l.Append(vals...)
return l
}
// synchronized
func (l *LinkedList[T]) Synchronize() {
l.mu = locker.NewRWLocker()
}
func (l *LinkedList[T]) Append(vals ...T) {
for _, v := range vals {
l.append(v)
}
}
// prepend will prepend the list with a value, the reference node is Returned
func (l *LinkedList[T]) Prepend(vals ...T) {
for _, v := range vals {
l.prepend(v)
}
}
func (l *LinkedList[T]) append(v T) {
n := createSingleNode(v)
l.mu.Lock()
defer l.mu.Unlock()
if l.head == nil {
l.head = n
}
if l.tail != nil {
l.tail.next = n
}
l.tail = n
l.size++
}
func (l *LinkedList[T]) prepend(v T) {
n := createSingleNode(v)
l.mu.Lock()
defer l.mu.Unlock()
if l.head != nil {
n.next = l.head
}
if l.tail == nil {
l.tail = n
}
l.head = n
l.size++
}
func (l *LinkedList[T]) PushHead() {
}
func (l *LinkedList[T]) PushTail() {
}
func (l *LinkedList[T]) Exist(v T) bool {
l.mu.RLock()
defer l.mu.RUnlock()
for current := l.head; current != nil; current = current.next {
if any(current.item) == any(v) {
return true
}
}
return false
}
func (l *LinkedList[T]) RemoveAt(index int) {
l.mu.Lock()
defer l.mu.Unlock()
var i int
var prev *linkedNode[T]
prev = l.head
for current := l.head; current != nil; {
if i == index {
prev.next = current.next
current.next = nil
l.size--
return
}
prev = current
current = current.next
i++
}
}
func (l *LinkedList[T]) IsEmpty() bool {
l.mu.RLock()
defer l.mu.RUnlock()
return l.size == 0
}
func (l *LinkedList[T]) Size() int {
l.mu.RLock()
defer l.mu.RUnlock()
return l.size
}
func (l *LinkedList[T]) GetAt(i int) T {
l.mu.RLock()
defer l.mu.RUnlock()
if i < l.size {
var n int
for current := l.head; current != nil; current = current.next {
if n == i {
return current.item
}
n++
}
}
return *new(T)
}
func (l *LinkedList[T]) ForEach(fn func(T) bool) {
l.mu.RLock()
defer l.mu.RUnlock()
for current := l.head; current != nil; current = current.next {
if fn(current.item) {
break
}
}
}
func (l *LinkedList[T]) Clear() {
l.mu.Lock()
defer l.mu.Unlock()
l.head = nil
l.tail = nil
l.size = 0
}
func (l *LinkedList[T]) ToList() []T {
l.mu.RLock()
defer l.mu.RUnlock()
ret := make([]T, 0, l.size)
for current := l.head; current != nil; current = current.next {
ret = append(ret, current.item)
}
return ret
}
func (l *LinkedList[T]) String() string {
l.mu.RLock()
defer l.mu.RUnlock()
ret := make([]T, 0, l.size)
for current := l.head; current != nil; current = current.next {
ret = append(ret, current.item)
}
return fmt.Sprint(ret)
}
func (l *LinkedList[T]) remove(n *linkedNode[T]) {
l.mu.Lock()
defer l.mu.Unlock()
n.next = nil
l.size--
}
type DLinkedList[T any] struct {
head, tail *doubleLinkedNode[T]
size int
}
// 初始化双向链表
func NewDoubleLinkedLis[T any]() *DLinkedList[T] {
return &DLinkedList[T]{}
}
func createSingleNode[T any](v T) *linkedNode[T] {
return &linkedNode[T]{item: v}
}
func createDoubleNode[T any](v T) *doubleLinkedNode[T] {
return &doubleLinkedNode[T]{item: v}
}