Skip to content

Commit 29014d0

Browse files
authored
Merge pull request #1442 from ydb-platform/xlist
internal/xlist changes
2 parents cd58c33 + 61f6195 commit 29014d0

File tree

3 files changed

+117
-85
lines changed

3 files changed

+117
-85
lines changed

internal/table/client.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ type Client struct {
8484
index map[*session]sessionInfo
8585
createInProgress int // KIKIMR-9163: in-create-process counter
8686
limit int // Upper bound for Client size.
87-
idle *xlist.List[*session]
88-
waitQ *xlist.List[*chan *session]
87+
idle xlist.List[*session]
88+
waitQ xlist.List[*chan *session]
8989
waitChPool sync.Pool
9090
testHookGetWaitCh func() // nil except some tests.
9191
wg sync.WaitGroup

internal/xlist/list.go

Lines changed: 97 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ type Element[T any] struct {
1212
next, prev *Element[T]
1313

1414
// The list to which this element belongs.
15-
list *List[T]
15+
list *list[T]
1616

1717
// The value stored with this element.
1818
Value T
@@ -38,29 +38,99 @@ func (e *Element[T]) Prev() *Element[T] {
3838

3939
// List represents a doubly linked list.
4040
// The zero value for List is an empty list ready to use.
41-
type List[T any] struct {
42-
root Element[T] // sentinel list element, only &root, root.prev, and root.next are used
43-
len int // current list length excluding (this) sentinel element
41+
type (
42+
List[T any] interface {
43+
// PushBack inserts a new element e with value v at the back of list l and returns e.
44+
PushBack(v T) *Element[T]
45+
46+
// PushBackList inserts a copy of another list at the back of list l.
47+
// The lists l and other may be the same. They must not be nil.
48+
PushBackList(other List[T])
49+
50+
// PushFront inserts a new element e with value v at the front of list l and returns e.
51+
PushFront(v T) *Element[T]
52+
53+
// PushFrontList inserts a copy of another list at the front of list l.
54+
// The lists l and other may be the same. They must not be nil.
55+
PushFrontList(other List[T])
56+
57+
// MoveToFront moves element e to the front of list l.
58+
// If e is not an element of l, the list is not modified.
59+
// The element must not be nil.
60+
MoveToFront(e *Element[T])
61+
62+
// MoveToBack moves element e to the back of list l.
63+
// If e is not an element of l, the list is not modified.
64+
// The element must not be nil.
65+
MoveToBack(e *Element[T])
66+
67+
// MoveAfter moves element e to its new position after mark.
68+
// If e or mark is not an element of l, or e == mark, the list is not modified.
69+
// The element and mark must not be nil.
70+
MoveAfter(e, mark *Element[T])
71+
72+
// MoveBefore moves element e to its new position before mark.
73+
// If e or mark is not an element of l, or e == mark, the list is not modified.
74+
// The element and mark must not be nil.
75+
MoveBefore(e, mark *Element[T])
76+
77+
// Remove removes e from l if e is an element of list l.
78+
// It returns the element value e.Value.
79+
// The element must not be nil.
80+
Remove(e *Element[T]) T
81+
82+
// InsertBefore inserts a new element e with value v immediately before mark and returns e.
83+
// If mark is not an element of l, the list is not modified.
84+
// The mark must not be nil.
85+
InsertBefore(v T, mark *Element[T]) *Element[T]
86+
87+
// InsertAfter inserts a new element e with value v immediately after mark and returns e.
88+
// If mark is not an element of l, the list is not modified.
89+
// The mark must not be nil.
90+
InsertAfter(v T, mark *Element[T]) *Element[T]
91+
92+
// Front returns the first element of list l or nil if the list is empty.
93+
Front() *Element[T]
94+
95+
// Back returns the last element of list l or nil if the list is empty.
96+
Back() *Element[T]
97+
98+
// Len returns the number of elements of list l.
99+
// The complexity is O(1).
100+
Len() int
101+
102+
// Clear clears the list l.
103+
Clear()
104+
}
105+
list[T any] struct {
106+
root Element[T] // sentinel list element, only &root, root.prev, and root.next are used
107+
len int // current list length excluding (this) sentinel element
108+
}
109+
)
110+
111+
// Clear clears the list l.
112+
func (l *list[T]) Clear() {
113+
l.root.next = &l.root
114+
l.root.prev = &l.root
115+
l.len = 0
44116
}
45117

46-
// Init initializes or clears list l.
47-
func (l *List[T]) Init() *List[T] {
118+
// New returns an initialized list.
119+
func New[T any]() List[T] {
120+
l := &list[T]{}
48121
l.root.next = &l.root
49122
l.root.prev = &l.root
50123
l.len = 0
51124

52125
return l
53126
}
54127

55-
// New returns an initialized list.
56-
func New[T any]() *List[T] { return new(List[T]).Init() }
57-
58128
// Len returns the number of elements of list l.
59129
// The complexity is O(1).
60-
func (l *List[T]) Len() int { return l.len }
130+
func (l *list[T]) Len() int { return l.len }
61131

62132
// Front returns the first element of list l or nil if the list is empty.
63-
func (l *List[T]) Front() *Element[T] {
133+
func (l *list[T]) Front() *Element[T] {
64134
if l.len == 0 {
65135
return nil
66136
}
@@ -69,23 +139,16 @@ func (l *List[T]) Front() *Element[T] {
69139
}
70140

71141
// Back returns the last element of list l or nil if the list is empty.
72-
func (l *List[T]) Back() *Element[T] {
142+
func (l *list[T]) Back() *Element[T] {
73143
if l.len == 0 {
74144
return nil
75145
}
76146

77147
return l.root.prev
78148
}
79149

80-
// lazyInit lazily initializes a zero List value.
81-
func (l *List[T]) lazyInit() {
82-
if l.root.next == nil {
83-
l.Init()
84-
}
85-
}
86-
87150
// insert inserts e after at, increments l.len, and returns e.
88-
func (l *List[T]) insert(e, at *Element[T]) *Element[T] {
151+
func (l *list[T]) insert(e, at *Element[T]) *Element[T] {
89152
e.prev = at
90153
e.next = at.next
91154
e.prev.next = e
@@ -97,12 +160,12 @@ func (l *List[T]) insert(e, at *Element[T]) *Element[T] {
97160
}
98161

99162
// insertValue is a convenience wrapper for insert(&Element{Value: v}, at).
100-
func (l *List[T]) insertValue(v T, at *Element[T]) *Element[T] {
163+
func (l *list[T]) insertValue(v T, at *Element[T]) *Element[T] {
101164
return l.insert(&Element[T]{Value: v}, at)
102165
}
103166

104167
// remove removes e from its list, decrements l.len
105-
func (l *List[T]) remove(e *Element[T]) {
168+
func (l *list[T]) remove(e *Element[T]) {
106169
e.prev.next = e.next
107170
e.next.prev = e.prev
108171
e.next = nil // avoid memory leaks
@@ -112,7 +175,7 @@ func (l *List[T]) remove(e *Element[T]) {
112175
}
113176

114177
// move moves e to next to at.
115-
func (l *List[T]) move(e, at *Element[T]) {
178+
func (l *list[T]) move(e, at *Element[T]) {
116179
if e == at {
117180
return
118181
}
@@ -128,7 +191,7 @@ func (l *List[T]) move(e, at *Element[T]) {
128191
// Remove removes e from l if e is an element of list l.
129192
// It returns the element value e.Value.
130193
// The element must not be nil.
131-
func (l *List[T]) Remove(e *Element[T]) T {
194+
func (l *list[T]) Remove(e *Element[T]) T {
132195
if e.list == l {
133196
// if e.list == l, l must have been initialized when e was inserted
134197
// in l or l == nil (e is a zero Element) and l.remove will crash
@@ -139,23 +202,19 @@ func (l *List[T]) Remove(e *Element[T]) T {
139202
}
140203

141204
// PushFront inserts a new element e with value v at the front of list l and returns e.
142-
func (l *List[T]) PushFront(v T) *Element[T] {
143-
l.lazyInit()
144-
205+
func (l *list[T]) PushFront(v T) *Element[T] {
145206
return l.insertValue(v, &l.root)
146207
}
147208

148209
// PushBack inserts a new element e with value v at the back of list l and returns e.
149-
func (l *List[T]) PushBack(v T) *Element[T] {
150-
l.lazyInit()
151-
210+
func (l *list[T]) PushBack(v T) *Element[T] {
152211
return l.insertValue(v, l.root.prev)
153212
}
154213

155214
// InsertBefore inserts a new element e with value v immediately before mark and returns e.
156215
// If mark is not an element of l, the list is not modified.
157216
// The mark must not be nil.
158-
func (l *List[T]) InsertBefore(v T, mark *Element[T]) *Element[T] {
217+
func (l *list[T]) InsertBefore(v T, mark *Element[T]) *Element[T] {
159218
if mark.list != l {
160219
return nil
161220
}
@@ -167,7 +226,7 @@ func (l *List[T]) InsertBefore(v T, mark *Element[T]) *Element[T] {
167226
// InsertAfter inserts a new element e with value v immediately after mark and returns e.
168227
// If mark is not an element of l, the list is not modified.
169228
// The mark must not be nil.
170-
func (l *List[T]) InsertAfter(v T, mark *Element[T]) *Element[T] {
229+
func (l *list[T]) InsertAfter(v T, mark *Element[T]) *Element[T] {
171230
if mark.list != l {
172231
return nil
173232
}
@@ -179,7 +238,7 @@ func (l *List[T]) InsertAfter(v T, mark *Element[T]) *Element[T] {
179238
// MoveToFront moves element e to the front of list l.
180239
// If e is not an element of l, the list is not modified.
181240
// The element must not be nil.
182-
func (l *List[T]) MoveToFront(e *Element[T]) {
241+
func (l *list[T]) MoveToFront(e *Element[T]) {
183242
if e.list != l || l.root.next == e {
184243
return
185244
}
@@ -190,7 +249,7 @@ func (l *List[T]) MoveToFront(e *Element[T]) {
190249
// MoveToBack moves element e to the back of list l.
191250
// If e is not an element of l, the list is not modified.
192251
// The element must not be nil.
193-
func (l *List[T]) MoveToBack(e *Element[T]) {
252+
func (l *list[T]) MoveToBack(e *Element[T]) {
194253
if e.list != l || l.root.prev == e {
195254
return
196255
}
@@ -201,7 +260,7 @@ func (l *List[T]) MoveToBack(e *Element[T]) {
201260
// MoveBefore moves element e to its new position before mark.
202261
// If e or mark is not an element of l, or e == mark, the list is not modified.
203262
// The element and mark must not be nil.
204-
func (l *List[T]) MoveBefore(e, mark *Element[T]) {
263+
func (l *list[T]) MoveBefore(e, mark *Element[T]) {
205264
if e.list != l || e == mark || mark.list != l {
206265
return
207266
}
@@ -211,7 +270,7 @@ func (l *List[T]) MoveBefore(e, mark *Element[T]) {
211270
// MoveAfter moves element e to its new position after mark.
212271
// If e or mark is not an element of l, or e == mark, the list is not modified.
213272
// The element and mark must not be nil.
214-
func (l *List[T]) MoveAfter(e, mark *Element[T]) {
273+
func (l *list[T]) MoveAfter(e, mark *Element[T]) {
215274
if e.list != l || e == mark || mark.list != l {
216275
return
217276
}
@@ -220,17 +279,15 @@ func (l *List[T]) MoveAfter(e, mark *Element[T]) {
220279

221280
// PushBackList inserts a copy of another list at the back of list l.
222281
// The lists l and other may be the same. They must not be nil.
223-
func (l *List[T]) PushBackList(other *List[T]) {
224-
l.lazyInit()
282+
func (l *list[T]) PushBackList(other List[T]) {
225283
for i, e := other.Len(), other.Front(); i > 0; i, e = i-1, e.Next() {
226284
l.insertValue(e.Value, l.root.prev)
227285
}
228286
}
229287

230288
// PushFrontList inserts a copy of another list at the front of list l.
231289
// The lists l and other may be the same. They must not be nil.
232-
func (l *List[T]) PushFrontList(other *List[T]) {
233-
l.lazyInit()
290+
func (l *list[T]) PushFrontList(other List[T]) {
234291
for i, e := other.Len(), other.Back(); i > 0; i, e = i-1, e.Prev() {
235292
l.insertValue(e.Value, &l.root)
236293
}

internal/xlist/list_test.go

Lines changed: 18 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package xlist
22

33
import "testing"
44

5-
func checkListLen[T comparable](t *testing.T, l *List[T], expectedLen int) bool {
5+
func checkListLen[T comparable](t *testing.T, l List[T], expectedLen int) bool {
66
if n := l.Len(); n != expectedLen {
77
t.Errorf("l.Len() = %d, want %d", n, expectedLen)
88

@@ -12,17 +12,19 @@ func checkListLen[T comparable](t *testing.T, l *List[T], expectedLen int) bool
1212
return true
1313
}
1414

15-
func checkListPointers[T comparable](t *testing.T, l *List[T], es []*Element[T]) {
16-
root := &l.root
15+
func checkListPointers[T comparable](t *testing.T, l List[T], es []*Element[T]) {
16+
root := &l.(*list[T]).root
1717

1818
if !checkListLen(t, l, len(es)) {
1919
return
2020
}
2121

2222
// zero length lists must be the zero value or properly initialized (sentinel circle)
2323
if len(es) == 0 {
24-
if l.root.next != nil && l.root.next != root || l.root.prev != nil && l.root.prev != root {
25-
t.Errorf("l.root.next = %p, l.root.prev = %p; both should both be nil or %p", l.root.next, l.root.prev, root)
24+
if l.(*list[T]).root.next != nil && l.(*list[T]).root.next != root ||
25+
l.(*list[T]).root.prev != nil && l.(*list[T]).root.prev != root {
26+
t.Errorf("l.root.next = %p, l.root.prev = %p; both should both be nil or %p",
27+
l.(*list[T]).root.next, l.(*list[T]).root.prev, root)
2628
}
2729

2830
return
@@ -145,7 +147,7 @@ func TestList(t *testing.T) {
145147
})
146148
}
147149

148-
func checkList[T comparable](t *testing.T, l *List[T], es []any) {
150+
func checkList[T comparable](t *testing.T, l List[T], es []any) {
149151
if !checkListLen(t, l, len(es)) {
150152
return
151153
}
@@ -289,66 +291,39 @@ func TestMove(t *testing.T) {
289291
checkListPointers(t, l, []*Element[int]{e1, e3, e2, e4})
290292
}
291293

292-
// Test PushFront, PushBack, PushFrontList, PushBackList with uninitialized List[T]
293-
func TestZeroList(t *testing.T) {
294-
t.Run("PushFront", func(t *testing.T) {
295-
l1 := new(List[int])
296-
l1.PushFront(1)
297-
checkList(t, l1, []any{1})
298-
299-
t.Run("PushFrontList", func(t *testing.T) {
300-
l3 := new(List[int])
301-
l3.PushFrontList(l1)
302-
checkList(t, l3, []any{1})
303-
})
304-
})
305-
306-
t.Run("PushBack", func(t *testing.T) {
307-
l2 := new(List[int])
308-
l2.PushBack(1)
309-
checkList(t, l2, []any{1})
310-
311-
t.Run("PushBackList", func(t *testing.T) {
312-
l4 := new(List[int])
313-
l4.PushBackList(l2)
314-
checkList(t, l4, []any{1})
315-
})
316-
})
317-
}
318-
319294
// Test that a list l is not modified when calling InsertBefore with a mark that is not an element of l.
320295
func TestInsertBeforeUnknownMark(t *testing.T) {
321-
var l List[int]
296+
l := New[int]()
322297
l.PushBack(1)
323298
l.PushBack(2)
324299
l.PushBack(3)
325300
l.InsertBefore(1, new(Element[int]))
326-
checkList(t, &l, []any{1, 2, 3})
301+
checkList(t, l, []any{1, 2, 3})
327302
}
328303

329304
// Test that a list l is not modified when calling InsertAfter with a mark that is not an element of l.
330305
func TestInsertAfterUnknownMark(t *testing.T) {
331-
var l List[int]
306+
l := New[int]()
332307
l.PushBack(1)
333308
l.PushBack(2)
334309
l.PushBack(3)
335310
l.InsertAfter(1, new(Element[int]))
336-
checkList(t, &l, []any{1, 2, 3})
311+
checkList(t, l, []any{1, 2, 3})
337312
}
338313

339314
// Test that a list l is not modified when calling MoveAfter or MoveBefore with a mark that is not an element of l.
340315
func TestMoveUnknownMark(t *testing.T) {
341-
var l1 List[int]
316+
l1 := New[int]()
342317
e1 := l1.PushBack(1)
343318

344-
var l2 List[int]
319+
l2 := New[int]()
345320
e2 := l2.PushBack(2)
346321

347322
l1.MoveAfter(e1, e2)
348-
checkList(t, &l1, []any{1})
349-
checkList(t, &l2, []any{2})
323+
checkList(t, l1, []any{1})
324+
checkList(t, l2, []any{2})
350325

351326
l1.MoveBefore(e1, e2)
352-
checkList(t, &l1, []any{1})
353-
checkList(t, &l2, []any{2})
327+
checkList(t, l1, []any{1})
328+
checkList(t, l2, []any{2})
354329
}

0 commit comments

Comments
 (0)