Skip to content

Commit

Permalink
add locker for racing
Browse files Browse the repository at this point in the history
  • Loading branch information
hedzr committed Jan 9, 2025
1 parent 173fa0f commit 993b03c
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 27 deletions.
82 changes: 56 additions & 26 deletions radix/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package radix
import (
"fmt"
"strings"
"sync"
"time"

"github.com/hedzr/evendeep"
Expand All @@ -28,6 +29,7 @@ type nodeS[T any] struct {
comment string
tag any
nType nodeType
rw *sync.RWMutex
}

var _ Node[any] = (*nodeS[any])(nil) // assertion helper
Expand All @@ -48,6 +50,26 @@ func (s *nodeS[T]) IsBranch() bool { return s.nType&NTMask == NTBranch } //
func (s *nodeS[T]) HasData() bool { return s.nType&NTData != 0 } //nolint:revive //data field is valid?
func (s *nodeS[T]) Empty() bool { return s.nType&NTData == 0 } //nolint:revive //data field is empty?

func (s *nodeS[T]) readLockFor(cb func(*nodeS[T])) { //nolint:revive
if s.rw != nil {
s.rw.RLock()
cb(s)
s.rw.RUnlock()
} else {
cb(s)
}
}

func (s *nodeS[T]) lockFor(cb func(*nodeS[T])) { //nolint:revive
if s.rw != nil {
s.rw.Lock()
cb(s)
s.rw.Unlock()
} else {
cb(s)
}
}

// SetModified sets the modified state to true or false.
//
// To clear the state, using ResetModified;
Expand Down Expand Up @@ -78,16 +100,20 @@ func (s *nodeS[T]) ResetModified() {
// Data returns the Data field of a node.
func (s *nodeS[T]) Data() (data T) {
// if !s.isBranch() {
data = s.data
s.readLockFor(func(s *nodeS[T]) {
data = s.data
})
// }
return
}

// SetData sets the Data field of a node.
func (s *nodeS[T]) SetData(data T) {
// if !s.isBranch() {
s.data = data
s.nType |= NTData
s.lockFor(func(s *nodeS[T]) {
s.data = data
s.nType |= NTData
})
// }
}

Expand All @@ -101,9 +127,11 @@ func (s *nodeS[T]) SetTTL(duration time.Duration, trie Trie[T], cb OnTTLRinging[
func (s *nodeS[T]) SetEmpty() {
// if !s.isBranch() {
// s.nType &= ^NTData
var t T
s.data = t
s.tag = nil
s.lockFor(func(s *nodeS[T]) {
var t T
s.data = t
s.tag = nil
})
// }
}

Expand Down Expand Up @@ -479,29 +507,31 @@ func (s *nodeS[T]) dumpR(sb *strings.Builder, lvl int, noColor bool) string { //
// }
}

if s.hasData() {
_, _ = sb.WriteString(" ")
_, _ = sb.WriteString(s.pathS)
_, _ = sb.WriteString(" => ")
_, _ = sb.WriteString(ColorToDim(fmt.Sprint(s.data)))
}
s.readLockFor(func(n *nodeS[T]) {
if s.hasData() {
_, _ = sb.WriteString(" ")
_, _ = sb.WriteString(s.pathS)
_, _ = sb.WriteString(" => ")
_, _ = sb.WriteString(ColorToDim(fmt.Sprint(s.Data())))
}

if s.comment != "" {
_, _ = sb.WriteString(ColorToColor(FgLightGreen, " // "+s.comment))
}
if s.comment != "" {
_, _ = sb.WriteString(ColorToColor(FgLightGreen, " // "+s.comment))
}

if s.tag != nil {
_, _ = sb.WriteString(" | tag = ")
_, _ = sb.WriteString(ColorToColor(FgGreen, fmt.Sprint(s.tag)))
}
if s.tag != nil {
_, _ = sb.WriteString(" | tag = ")
_, _ = sb.WriteString(ColorToColor(FgGreen, fmt.Sprint(s.tag)))
}

if s.description != "" {
_, _ = sb.WriteString(ColorToColor(FgLightGreen, " ~ "+s.description))
}
if s.description != "" {
_, _ = sb.WriteString(ColorToColor(FgLightGreen, " ~ "+s.description))
}

if !strings.HasSuffix(s.pathS, string(s.path)) {
_, _ = fmt.Fprintf(sb, " [WRONG path & pathS: %q / %q]", string(s.path), s.pathS)
}
if !strings.HasSuffix(s.pathS, string(s.path)) {
_, _ = fmt.Fprintf(sb, " [WRONG path & pathS: %q / %q]", string(s.path), s.pathS)
}
})
_ = sb.WriteByte('\n')
}

Expand All @@ -526,7 +556,7 @@ func (s *nodeS[T]) Dup() (newNode *nodeS[T]) { //nolint:revive
newNode.children = append(newNode.children, ch.Dup())
}

data := evendeep.MakeClone(s.data)
data := evendeep.MakeClone(s.Data())
switch z := data.(type) {
case *T:
newNode.data = *z
Expand Down
8 changes: 7 additions & 1 deletion radix/trie.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ func (s *TTL[T]) Close() {
func (s *TTL[T]) Tree() Trie[T] { return s.treevec[0] }

func (s *TTL[T]) Add(nd *nodeS[T], duration time.Duration, action OnTTLRinging[T]) {
if nd.rw == nil {
nd.rw = &sync.RWMutex{}
}
s.adder <- ttljobS[T]{node: nd, duration: duration, action: action}
}

Expand All @@ -116,6 +119,7 @@ func (s *TTL[T]) run() {
timer := time.NewTimer(job.duration)
go func(timer *time.Timer, job ttljobS[T]) {
defer timer.Stop()
// defer func() { job.node.rw = nil }()
for {
select {
case <-timer.C:
Expand Down Expand Up @@ -581,7 +585,9 @@ func (s *trieS[T]) Query(path string, kvpair KVPair) (data T, branch, found bool
}
}
if node.hasData() {
data = node.data
node.lockFor(func(n *nodeS[T]) {
data = node.data
})
}
}
// if !found {
Expand Down

0 comments on commit 993b03c

Please sign in to comment.