Iterators in XMLProvider doing the locking

This commit is contained in:
Simon Martens
2025-03-16 21:10:52 +01:00
parent 534fabcb54
commit 5681f4f352
3 changed files with 59 additions and 29 deletions

View File

@@ -1,6 +1,7 @@
package xmlparsing
import (
"iter"
"slices"
"sync"
"time"
@@ -36,7 +37,6 @@ type XMLParser[T IXMLItem] struct {
// INFO: map is type map[string]*T
Items sync.Map
// INFO: map is type [string]ItemInfo
// It keeps information about parsing status of the items.
Infos sync.Map
// INFO: Resolver is used to resolve references (back-links) between XML items.
@@ -44,8 +44,7 @@ type XMLParser[T IXMLItem] struct {
mu sync.RWMutex
// TODO: This array is meant to be for iteration purposes, since iteration over the sync.Map is slow.
// It is best for this array to be sorted by key of the corresponding item.
Array []T
array []T
}
func NewXMLParser[T IXMLItem]() *XMLParser[T] {
@@ -59,7 +58,7 @@ func (p *XMLParser[T]) Prepare() {
p.mu.Lock()
defer p.mu.Unlock()
p.Array = make([]T, 0, len(p.Array))
p.array = make([]T, 0, len(p.array))
p.Resolver.Clear()
}
@@ -82,7 +81,7 @@ func (p *XMLParser[T]) Serialize(dataholder XMLRootElement[T], path string, late
p.mu.Lock()
defer p.mu.Unlock()
p.Array = append(p.Array, newItems...)
p.array = append(p.array, newItems...)
return nil
}
@@ -118,7 +117,7 @@ func (p *XMLParser[T]) Cleanup(latest ParseMeta) {
p.mu.Lock()
defer p.mu.Unlock()
for _, item := range toappend {
p.Array = append(p.Array, *item)
p.array = append(p.array, *item)
p.addResolvable(*item)
}
}
@@ -151,8 +150,10 @@ func (p *XMLParser[T]) ReverseLookup(item IXMLItem) []Resolved[T] {
}
func (a *XMLParser[T]) String() string {
a.RLock()
defer a.RUnlock()
var s string
for _, item := range a.Array {
for _, item := range a.array {
s += item.String()
}
return s
@@ -176,23 +177,41 @@ func (p *XMLParser[T]) Item(id string) *T {
return i
}
func (p *XMLParser[T]) Find(fn func(*T) bool) []T {
func (p *XMLParser[T]) Filter(f func(T) bool) iter.Seq[T] {
return func(yield func(T) bool) {
p.mu.RLock()
defer p.mu.RUnlock()
var items []T
for _, item := range p.Array {
if fn(&item) {
items = append(items, item)
for _, v := range p.array {
if f(v) && !yield(v) {
return
}
}
}
return items
}
// INFO: These are only reading locks.
func (p *XMLParser[T]) Lock() {
func (p *XMLParser[T]) Iterate() iter.Seq[T] {
return func(yield func(T) bool) {
p.mu.RLock()
defer p.mu.RUnlock()
for _, v := range p.array {
if !yield(v) {
return
}
}
}
}
func (p *XMLParser[T]) Count() int {
p.RLock()
defer p.RUnlock()
return len(p.array)
}
// INFO: These are reading locks.
func (p *XMLParser[T]) RLock() {
p.mu.RLock()
}
func (p *XMLParser[T]) Unlock() {
func (p *XMLParser[T]) RUnlock() {
p.mu.RUnlock()
}

View File

@@ -11,6 +11,7 @@ type Letter struct {
Pages []Page `xml:"page"`
Hands []RefElement `xml:"hand"`
Content string `xml:",innerxml"`
Chardata string `xml:",chardata"`
}
func (l Letter) Keys() []any {

View File

@@ -37,27 +37,37 @@ func (l *Library) String() string {
sb := strings.Builder{}
sb.WriteString("Persons: ")
sb.WriteString(strconv.Itoa(len(l.Persons.Array)))
sb.WriteString(strconv.Itoa(l.Persons.Count()))
sb.WriteString("\n")
sb.WriteString("Places: ")
sb.WriteString(strconv.Itoa(len(l.Places.Array)))
sb.WriteString(strconv.Itoa(l.Places.Count()))
sb.WriteString("\n")
sb.WriteString("AppDefs: ")
sb.WriteString(strconv.Itoa(len(l.AppDefs.Array)))
sb.WriteString(strconv.Itoa(l.AppDefs.Count()))
sb.WriteString("\n")
sb.WriteString("Letters: ")
sb.WriteString(strconv.Itoa(len(l.Letters.Array)))
sb.WriteString(strconv.Itoa(l.Letters.Count()))
filter := func(item Letter) bool {
return len(item.Hands) > 0
}
hands := 0
for l := range l.Letters.Filter(filter) {
hands += 1
sb.WriteString("\n")
sb.WriteString(strconv.Itoa(l.Letter) + ": ")
sb.WriteString(strconv.Itoa(len(l.Hands)) + " Hände, No " + strconv.Itoa(hands))
}
sb.WriteString("\n")
sb.WriteString("Traditions: ")
sb.WriteString(strconv.Itoa(len(l.Traditions.Array)))
sb.WriteString(strconv.Itoa(l.Traditions.Count()))
sb.WriteString("\n")
sb.WriteString("Metas: ")
sb.WriteString(strconv.Itoa(len(l.Metas.Array)))
sb.WriteString(strconv.Itoa(l.Metas.Count()))
sb.WriteString("\n")
return sb.String()