diff --git a/internal/libs/clist/bench_test.go b/internal/libs/clist/bench_test.go index 95973cc76..ee5d836a7 100644 --- a/internal/libs/clist/bench_test.go +++ b/internal/libs/clist/bench_test.go @@ -12,7 +12,7 @@ func BenchmarkDetaching(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { start.removed = true - start.DetachNext() + start.detachNext() start.DetachPrev() tmp := nxt nxt = nxt.Next() diff --git a/internal/libs/clist/clist.go b/internal/libs/clist/clist.go index 99e5f05bf..3969c94cc 100644 --- a/internal/libs/clist/clist.go +++ b/internal/libs/clist/clist.go @@ -44,7 +44,6 @@ waiting on NextWait() (since it's just a read operation). type CElement struct { mtx sync.RWMutex prev *CElement - prevWaitCh chan struct{} next *CElement nextWaitCh chan struct{} 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, // channel will be closed. func (e *CElement) NextWaitChan() <-chan struct{} { @@ -131,7 +103,7 @@ func (e *CElement) Removed() bool { return isRemoved } -func (e *CElement) DetachNext() { +func (e *CElement) detachNext() { e.mtx.Lock() if !e.removed { e.mtx.Unlock() @@ -153,7 +125,7 @@ func (e *CElement) DetachPrev() { // NOTE: This function needs to be safe for // concurrent goroutines waiting on nextWg. -func (e *CElement) SetNext(newNext *CElement) { +func (e *CElement) setNext(newNext *CElement) { e.mtx.Lock() oldNext := e.next @@ -174,30 +146,20 @@ func (e *CElement) SetNext(newNext *CElement) { // NOTE: This function needs to be safe for // concurrent goroutines waiting on prevWg -func (e *CElement) SetPrev(newPrev *CElement) { +func (e *CElement) setPrev(newPrev *CElement) { e.mtx.Lock() defer e.mtx.Unlock() - oldPrev := e.prev 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() defer e.mtx.Unlock() 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 { close(e.nextWaitCh) } @@ -211,7 +173,6 @@ func (e *CElement) SetRemoved() { // Panics if length grows beyond the max. type CList struct { mtx sync.RWMutex - wg *sync.WaitGroup waitCh chan struct{} head *CElement // first element tail *CElement // last element @@ -250,7 +211,7 @@ func (l *CList) Front() *CElement { return head } -func (l *CList) FrontWait() *CElement { +func (l *CList) frontWait() *CElement { // Loop until the head is non-nil else wait and try again for { l.mtx.RLock() @@ -273,22 +234,6 @@ func (l *CList) Back() *CElement { 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 // does, channel will be closed. func (l *CList) WaitChan() <-chan struct{} { @@ -305,7 +250,6 @@ func (l *CList) PushBack(v interface{}) *CElement { // Construct a new element e := &CElement{ prev: nil, - prevWaitCh: make(chan struct{}), next: nil, nextWaitCh: make(chan struct{}), removed: false, @@ -326,8 +270,8 @@ func (l *CList) PushBack(v interface{}) *CElement { l.head = e l.tail = e } 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.mtx.Unlock() @@ -365,16 +309,16 @@ func (l *CList) Remove(e *CElement) interface{} { if prev == nil { l.head = next } else { - prev.SetNext(next) + prev.setNext(next) } if next == nil { l.tail = prev } else { - next.SetPrev(prev) + next.setPrev(prev) } // Set .Done() on e, otherwise waiters will wait forever. - e.SetRemoved() + e.setRemoved() return e.Value } diff --git a/internal/libs/clist/clist_test.go b/internal/libs/clist/clist_test.go index a0482fc40..a0449a985 100644 --- a/internal/libs/clist/clist_test.go +++ b/internal/libs/clist/clist_test.go @@ -218,7 +218,7 @@ func TestScanRightDeleteRandom(t *testing.T) { default: } if el == nil { - el = l.FrontWait() + el = l.frontWait() restartCounter++ } 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) } - // 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) {