Skip to content

Commit 350e895

Browse files
committed
feat: 添加copy on write list实现
1 parent 6fdf3ad commit 350e895

File tree

2 files changed

+508
-0
lines changed

2 files changed

+508
-0
lines changed

list/copy_on_write_array_list.go

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
package list
2+
3+
import (
4+
"sync"
5+
6+
"github.com/ecodeclub/ekit/internal/errs"
7+
"github.com/ecodeclub/ekit/internal/slice"
8+
)
9+
10+
var (
11+
_ List[any] = &CopyOnWriteArrayList[any]{}
12+
)
13+
14+
// CopyOnWriteArrayList 基于切片的简单封装 写时加锁,读不加锁,适合于读多写少场景
15+
type CopyOnWriteArrayList[T any] struct {
16+
vals []T
17+
mutex *sync.Mutex
18+
}
19+
20+
// NewCopyOnWriteArrayList
21+
func NewCopyOnWriteArrayList[T any]() *CopyOnWriteArrayList[T] {
22+
m := &sync.Mutex{}
23+
return &CopyOnWriteArrayList[T]{
24+
vals: make([]T, 0),
25+
mutex: m,
26+
}
27+
}
28+
29+
// NewCopyOnWriteArrayListOf 直接使用 ts,会执行复制
30+
func NewCopyOnWriteArrayListOf[T any](ts []T) *CopyOnWriteArrayList[T] {
31+
items := make([]T, len(ts))
32+
copy(items, ts)
33+
m := &sync.Mutex{}
34+
return &CopyOnWriteArrayList[T]{
35+
vals: items,
36+
mutex: m,
37+
}
38+
}
39+
40+
func (a *CopyOnWriteArrayList[T]) Get(index int) (t T, e error) {
41+
l := a.Len()
42+
if index < 0 || index >= l {
43+
return t, errs.NewErrIndexOutOfRange(l, index)
44+
}
45+
return a.vals[index], e
46+
}
47+
48+
// Append 往CopyOnWriteArrayList里追加数据
49+
func (a *CopyOnWriteArrayList[T]) Append(ts ...T) error {
50+
a.mutex.Lock()
51+
defer a.mutex.Unlock()
52+
n := len(a.vals)
53+
newItems := make([]T, n, n+len(ts))
54+
copy(newItems, a.vals)
55+
newItems = append(newItems, ts...)
56+
a.vals = newItems
57+
return nil
58+
}
59+
60+
// Add 在CopyOnWriteArrayList下标为index的位置插入一个元素
61+
// 当index等于CopyOnWriteArrayList长度等同于append
62+
func (a *CopyOnWriteArrayList[T]) Add(index int, t T) (err error) {
63+
a.mutex.Lock()
64+
defer a.mutex.Unlock()
65+
n := len(a.vals)
66+
newItems := make([]T, n, n+1)
67+
copy(newItems, a.vals)
68+
newItems, err = slice.Add(newItems, t, index)
69+
a.vals = newItems
70+
return
71+
}
72+
73+
// Set 设置CopyOnWriteArrayList里index位置的值为t
74+
func (a *CopyOnWriteArrayList[T]) Set(index int, t T) error {
75+
a.mutex.Lock()
76+
defer a.mutex.Unlock()
77+
n := len(a.vals)
78+
if index >= n || index < 0 {
79+
return errs.NewErrIndexOutOfRange(n, index)
80+
}
81+
newItems := make([]T, n)
82+
copy(newItems, a.vals)
83+
newItems[index] = t
84+
a.vals = newItems
85+
return nil
86+
}
87+
88+
// 这里不涉及缩容,每次都是当前内容长度申请的数组容量
89+
func (a *CopyOnWriteArrayList[T]) Delete(index int) (T, error) {
90+
a.mutex.Lock()
91+
defer a.mutex.Unlock()
92+
newItems := make([]T, len(a.vals))
93+
copy(newItems, a.vals)
94+
res, t, err := slice.Delete(newItems, index)
95+
if err != nil {
96+
return t, err
97+
}
98+
newItems = res
99+
a.vals = newItems
100+
return t, nil
101+
}
102+
103+
func (a *CopyOnWriteArrayList[T]) Len() int {
104+
return len(a.vals)
105+
}
106+
107+
func (a *CopyOnWriteArrayList[T]) Cap() int {
108+
return cap(a.vals)
109+
}
110+
111+
func (a *CopyOnWriteArrayList[T]) Range(fn func(index int, t T) error) error {
112+
for key, value := range a.vals {
113+
e := fn(key, value)
114+
if e != nil {
115+
return e
116+
}
117+
}
118+
return nil
119+
}
120+
121+
func (a *CopyOnWriteArrayList[T]) AsSlice() []T {
122+
a.mutex.Lock()
123+
defer a.mutex.Unlock()
124+
res := make([]T, len(a.vals))
125+
copy(res, a.vals)
126+
return res
127+
}

0 commit comments

Comments
 (0)