mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-12 07:42:48 +00:00
Compare commits
2 Commits
main-libp2
...
clist-wait
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7497331f47 | ||
|
|
d893463bb8 |
@@ -12,7 +12,6 @@ func BenchmarkDetaching(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
start.removed = true
|
||||
start.DetachNext()
|
||||
start.DetachPrev()
|
||||
tmp := nxt
|
||||
nxt = nxt.Next()
|
||||
@@ -30,7 +29,6 @@ func BenchmarkRemoved(b *testing.B) {
|
||||
nxt := start.Next()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
start.Removed()
|
||||
tmp := nxt
|
||||
nxt = nxt.Next()
|
||||
start = tmp
|
||||
|
||||
@@ -44,14 +44,12 @@ waiting on NextWait() (since it's just a read operation).
|
||||
|
||||
*/
|
||||
type CElement struct {
|
||||
mtx tmsync.RWMutex
|
||||
prev *CElement
|
||||
prevWg *sync.WaitGroup
|
||||
prevWaitCh chan struct{}
|
||||
next *CElement
|
||||
nextWg *sync.WaitGroup
|
||||
nextWaitCh chan struct{}
|
||||
removed bool
|
||||
mtx tmsync.RWMutex
|
||||
prev *CElement
|
||||
prevWg *sync.WaitGroup
|
||||
next *CElement
|
||||
nextWg *sync.WaitGroup
|
||||
removed bool
|
||||
|
||||
Value interface{} // immutable
|
||||
}
|
||||
@@ -94,22 +92,36 @@ func (e *CElement) PrevWait() *CElement {
|
||||
}
|
||||
}
|
||||
|
||||
// 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{} {
|
||||
e.mtx.RLock()
|
||||
defer e.mtx.RUnlock()
|
||||
wg := e.nextWg
|
||||
|
||||
return e.nextWaitCh
|
||||
ret := make(chan struct{})
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(ret)
|
||||
}()
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// 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()
|
||||
wg := e.prevWg
|
||||
|
||||
ret := make(chan struct{})
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(ret)
|
||||
}()
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// Nonblocking, may return nil if at the end.
|
||||
@@ -128,23 +140,6 @@ func (e *CElement) Prev() *CElement {
|
||||
return prev
|
||||
}
|
||||
|
||||
func (e *CElement) Removed() bool {
|
||||
e.mtx.RLock()
|
||||
isRemoved := e.removed
|
||||
e.mtx.RUnlock()
|
||||
return isRemoved
|
||||
}
|
||||
|
||||
func (e *CElement) DetachNext() {
|
||||
e.mtx.Lock()
|
||||
if !e.removed {
|
||||
e.mtx.Unlock()
|
||||
panic("DetachNext() must be called after Remove(e)")
|
||||
}
|
||||
e.next = nil
|
||||
e.mtx.Unlock()
|
||||
}
|
||||
|
||||
func (e *CElement) DetachPrev() {
|
||||
e.mtx.Lock()
|
||||
if !e.removed {
|
||||
@@ -169,11 +164,9 @@ func (e *CElement) SetNext(newNext *CElement) {
|
||||
// events, new Add calls must happen after all previous Wait calls have
|
||||
// returned.
|
||||
e.nextWg = waitGroup1() // WaitGroups are difficult to re-use.
|
||||
e.nextWaitCh = make(chan struct{})
|
||||
}
|
||||
if oldNext == nil && newNext != nil {
|
||||
e.nextWg.Done()
|
||||
close(e.nextWaitCh)
|
||||
}
|
||||
e.mtx.Unlock()
|
||||
}
|
||||
@@ -187,11 +180,9 @@ func (e *CElement) SetPrev(newPrev *CElement) {
|
||||
e.prev = newPrev
|
||||
if oldPrev != nil && newPrev == nil {
|
||||
e.prevWg = waitGroup1() // WaitGroups are difficult to re-use.
|
||||
e.prevWaitCh = make(chan struct{})
|
||||
}
|
||||
if oldPrev == nil && newPrev != nil {
|
||||
e.prevWg.Done()
|
||||
close(e.prevWaitCh)
|
||||
}
|
||||
e.mtx.Unlock()
|
||||
}
|
||||
@@ -204,11 +195,9 @@ func (e *CElement) SetRemoved() {
|
||||
// This wakes up anyone waiting in either direction.
|
||||
if e.prev == nil {
|
||||
e.prevWg.Done()
|
||||
close(e.prevWaitCh)
|
||||
}
|
||||
if e.next == nil {
|
||||
e.nextWg.Done()
|
||||
close(e.nextWaitCh)
|
||||
}
|
||||
e.mtx.Unlock()
|
||||
}
|
||||
@@ -222,7 +211,6 @@ func (e *CElement) SetRemoved() {
|
||||
type CList struct {
|
||||
mtx tmsync.RWMutex
|
||||
wg *sync.WaitGroup
|
||||
waitCh chan struct{}
|
||||
head *CElement // first element
|
||||
tail *CElement // last element
|
||||
len int // list length
|
||||
@@ -239,7 +227,6 @@ func newWithMax(maxLength int) *CList {
|
||||
l.maxLen = maxLength
|
||||
|
||||
l.wg = waitGroup1()
|
||||
l.waitCh = make(chan struct{})
|
||||
l.head = nil
|
||||
l.tail = nil
|
||||
l.len = 0
|
||||
@@ -303,10 +290,17 @@ func (l *CList) BackWait() *CElement {
|
||||
// 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{} {
|
||||
l.mtx.Lock()
|
||||
defer l.mtx.Unlock()
|
||||
l.mtx.RLock()
|
||||
defer l.mtx.RUnlock()
|
||||
wg := l.wg
|
||||
|
||||
return l.waitCh
|
||||
ret := make(chan struct{})
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(ret)
|
||||
}()
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// Panics if list grows beyond its max length.
|
||||
@@ -315,20 +309,17 @@ func (l *CList) PushBack(v interface{}) *CElement {
|
||||
|
||||
// Construct a new element
|
||||
e := &CElement{
|
||||
prev: nil,
|
||||
prevWg: waitGroup1(),
|
||||
prevWaitCh: make(chan struct{}),
|
||||
next: nil,
|
||||
nextWg: waitGroup1(),
|
||||
nextWaitCh: make(chan struct{}),
|
||||
removed: false,
|
||||
Value: v,
|
||||
prev: nil,
|
||||
prevWg: waitGroup1(),
|
||||
next: nil,
|
||||
nextWg: waitGroup1(),
|
||||
removed: false,
|
||||
Value: v,
|
||||
}
|
||||
|
||||
// Release waiters on FrontWait/BackWait maybe
|
||||
if l.len == 0 {
|
||||
l.wg.Done()
|
||||
close(l.waitCh)
|
||||
}
|
||||
if l.len >= l.maxLen {
|
||||
panic(fmt.Sprintf("clist: maximum length list reached %d", l.maxLen))
|
||||
@@ -372,7 +363,6 @@ func (l *CList) Remove(e *CElement) interface{} {
|
||||
// If we're removing the only item, make CList FrontWait/BackWait wait.
|
||||
if l.len == 1 {
|
||||
l.wg = waitGroup1() // WaitGroups are difficult to re-use.
|
||||
l.waitCh = make(chan struct{})
|
||||
}
|
||||
|
||||
// Update l.len
|
||||
|
||||
Reference in New Issue
Block a user