Browse Source

libs/clist: remove unused surface area (#8134)

wb/add-nullable-false
Sam Kleinman 3 years ago
committed by GitHub
parent
commit
bedb68078c
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 13 additions and 93 deletions
  1. +1
    -1
      internal/libs/clist/bench_test.go
  2. +11
    -67
      internal/libs/clist/clist.go
  3. +1
    -25
      internal/libs/clist/clist_test.go

+ 1
- 1
internal/libs/clist/bench_test.go View File

@ -12,7 +12,7 @@ func BenchmarkDetaching(b *testing.B) {
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
start.removed = true start.removed = true
start.DetachNext()
start.detachNext()
start.DetachPrev() start.DetachPrev()
tmp := nxt tmp := nxt
nxt = nxt.Next() nxt = nxt.Next()


+ 11
- 67
internal/libs/clist/clist.go View File

@ -44,7 +44,6 @@ waiting on NextWait() (since it's just a read operation).
type CElement struct { type CElement struct {
mtx sync.RWMutex mtx sync.RWMutex
prev *CElement prev *CElement
prevWaitCh chan struct{}
next *CElement next *CElement
nextWaitCh chan struct{} nextWaitCh chan struct{}
removed bool removed bool
@ -72,33 +71,6 @@ func (e *CElement) NextWait() *CElement {
} }
} }
// Blocking implementation of Prev().
// May return nil iff CElement was head and got removed.
func (e *CElement) PrevWait() *CElement {
for {
e.mtx.RLock()
prev := e.prev
removed := e.removed
signal := e.prevWaitCh
e.mtx.RUnlock()
if prev != nil || removed {
return prev
}
<-signal
}
}
// PrevWaitChan can be used to wait until Prev becomes not nil. Once it does,
// channel will be closed.
func (e *CElement) PrevWaitChan() <-chan struct{} {
e.mtx.RLock()
defer e.mtx.RUnlock()
return e.prevWaitCh
}
// NextWaitChan can be used to wait until Next becomes not nil. Once it does, // NextWaitChan can be used to wait until Next becomes not nil. Once it does,
// channel will be closed. // channel will be closed.
func (e *CElement) NextWaitChan() <-chan struct{} { func (e *CElement) NextWaitChan() <-chan struct{} {
@ -131,7 +103,7 @@ func (e *CElement) Removed() bool {
return isRemoved return isRemoved
} }
func (e *CElement) DetachNext() {
func (e *CElement) detachNext() {
e.mtx.Lock() e.mtx.Lock()
if !e.removed { if !e.removed {
e.mtx.Unlock() e.mtx.Unlock()
@ -153,7 +125,7 @@ func (e *CElement) DetachPrev() {
// NOTE: This function needs to be safe for // NOTE: This function needs to be safe for
// concurrent goroutines waiting on nextWg. // concurrent goroutines waiting on nextWg.
func (e *CElement) SetNext(newNext *CElement) {
func (e *CElement) setNext(newNext *CElement) {
e.mtx.Lock() e.mtx.Lock()
oldNext := e.next oldNext := e.next
@ -174,30 +146,20 @@ func (e *CElement) SetNext(newNext *CElement) {
// NOTE: This function needs to be safe for // NOTE: This function needs to be safe for
// concurrent goroutines waiting on prevWg // concurrent goroutines waiting on prevWg
func (e *CElement) SetPrev(newPrev *CElement) {
func (e *CElement) setPrev(newPrev *CElement) {
e.mtx.Lock() e.mtx.Lock()
defer e.mtx.Unlock() defer e.mtx.Unlock()
oldPrev := e.prev
e.prev = newPrev e.prev = newPrev
if oldPrev != nil && newPrev == nil {
e.prevWaitCh = make(chan struct{})
}
if oldPrev == nil && newPrev != nil {
close(e.prevWaitCh)
}
} }
func (e *CElement) SetRemoved() {
func (e *CElement) setRemoved() {
e.mtx.Lock() e.mtx.Lock()
defer e.mtx.Unlock() defer e.mtx.Unlock()
e.removed = true e.removed = true
// This wakes up anyone waiting in either direction.
if e.prev == nil {
close(e.prevWaitCh)
}
// This wakes up anyone waiting.
if e.next == nil { if e.next == nil {
close(e.nextWaitCh) close(e.nextWaitCh)
} }
@ -211,7 +173,6 @@ func (e *CElement) SetRemoved() {
// Panics if length grows beyond the max. // Panics if length grows beyond the max.
type CList struct { type CList struct {
mtx sync.RWMutex mtx sync.RWMutex
wg *sync.WaitGroup
waitCh chan struct{} waitCh chan struct{}
head *CElement // first element head *CElement // first element
tail *CElement // last element tail *CElement // last element
@ -250,7 +211,7 @@ func (l *CList) Front() *CElement {
return head return head
} }
func (l *CList) FrontWait() *CElement {
func (l *CList) frontWait() *CElement {
// Loop until the head is non-nil else wait and try again // Loop until the head is non-nil else wait and try again
for { for {
l.mtx.RLock() l.mtx.RLock()
@ -273,22 +234,6 @@ func (l *CList) Back() *CElement {
return back return back
} }
func (l *CList) BackWait() *CElement {
for {
l.mtx.RLock()
tail := l.tail
wg := l.wg
l.mtx.RUnlock()
if tail != nil {
return tail
}
wg.Wait()
// l.tail doesn't necessarily exist here.
// That's why we need to continue a for-loop.
}
}
// WaitChan can be used to wait until Front or Back becomes not nil. Once it // WaitChan can be used to wait until Front or Back becomes not nil. Once it
// does, channel will be closed. // does, channel will be closed.
func (l *CList) WaitChan() <-chan struct{} { func (l *CList) WaitChan() <-chan struct{} {
@ -305,7 +250,6 @@ func (l *CList) PushBack(v interface{}) *CElement {
// Construct a new element // Construct a new element
e := &CElement{ e := &CElement{
prev: nil, prev: nil,
prevWaitCh: make(chan struct{}),
next: nil, next: nil,
nextWaitCh: make(chan struct{}), nextWaitCh: make(chan struct{}),
removed: false, removed: false,
@ -326,8 +270,8 @@ func (l *CList) PushBack(v interface{}) *CElement {
l.head = e l.head = e
l.tail = e l.tail = e
} else { } else {
e.SetPrev(l.tail) // We must init e first.
l.tail.SetNext(e) // This will make e accessible.
e.setPrev(l.tail) // We must init e first.
l.tail.setNext(e) // This will make e accessible.
l.tail = e // Update the list. l.tail = e // Update the list.
} }
l.mtx.Unlock() l.mtx.Unlock()
@ -365,16 +309,16 @@ func (l *CList) Remove(e *CElement) interface{} {
if prev == nil { if prev == nil {
l.head = next l.head = next
} else { } else {
prev.SetNext(next)
prev.setNext(next)
} }
if next == nil { if next == nil {
l.tail = prev l.tail = prev
} else { } else {
next.SetPrev(prev)
next.setPrev(prev)
} }
// Set .Done() on e, otherwise waiters will wait forever. // Set .Done() on e, otherwise waiters will wait forever.
e.SetRemoved()
e.setRemoved()
return e.Value return e.Value
} }

+ 1
- 25
internal/libs/clist/clist_test.go View File

@ -218,7 +218,7 @@ func TestScanRightDeleteRandom(t *testing.T) {
default: default:
} }
if el == nil { if el == nil {
el = l.FrontWait()
el = l.frontWait()
restartCounter++ restartCounter++
} }
el = el.Next() el = el.Next()
@ -314,30 +314,6 @@ FOR_LOOP:
t.Fatalf("number of pushed items (%d) not equal to number of seen items (%d)", pushed, seen) t.Fatalf("number of pushed items (%d) not equal to number of seen items (%d)", pushed, seen)
} }
// 4) test iterating backwards (PrevWaitChan and Prev)
prev := next
seen = 0
FOR_LOOP2:
for {
select {
case <-prev.PrevWaitChan():
prev = prev.Prev()
seen++
if prev == nil {
t.Fatal("expected PrevWaitChan to block forever on nil when reached first elem")
}
if pushed == seen {
break FOR_LOOP2
}
case <-time.After(250 * time.Millisecond):
break FOR_LOOP2
}
}
if pushed != seen {
t.Fatalf("number of pushed items (%d) not equal to number of seen items (%d)", pushed, seen)
}
} }
func TestRemoved(t *testing.T) { func TestRemoved(t *testing.T) {


Loading…
Cancel
Save