Skip to content

Commit

Permalink
add thread safe map
Browse files Browse the repository at this point in the history
  • Loading branch information
foolin committed May 3, 2020
1 parent fbdc82b commit 7c0044d
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 16 deletions.
4 changes: 2 additions & 2 deletions builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ var builtinFun BuiltinFunctions
var builtinSel BuiltinSelections

//builtin functions
var builtinFuncMap = map[string]CallFunc{
var builtinFuncs = map[string]CallFunc{
"absHref": builtinFun.AbsHref,
"attr": builtinFun.Attr,
"attrConcat": builtinFun.AttrConcat,
Expand Down Expand Up @@ -94,5 +94,5 @@ var builtinFuncMap = map[string]CallFunc{
// return "Hello", nil
// })
func (p *Pagser) RegisterFunc(name string, fn CallFunc) {
p.ctxFuncs[name] = fn
p.mapFuncs.Store(name, fn)
}
27 changes: 18 additions & 9 deletions pagser.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,18 @@

package pagser

import "errors"
import (
"errors"
"sync"
)

// Pagser the page parser
type Pagser struct {
Config Config
ctxTags map[string]*tagTokenizer // tag value => tagTokenizer
ctxFuncs map[string]CallFunc // name => func
Config Config
//ctxTags map[string]*tagTokenizer // tag value => tagTokenizer
mapTags sync.Map //map[string]*tagTokenizer
//ctxFuncs map[string]CallFunc // name => func
mapFuncs sync.Map //map[string]CallFunc
}

// New create pagser client
Expand All @@ -31,9 +36,13 @@ func NewWithConfig(cfg Config) (*Pagser, error) {
if cfg.FuncSymbol == "" {
return nil, errors.New("FuncSymbol must not empty")
}
return &Pagser{
Config: cfg,
ctxTags: make(map[string]*tagTokenizer, 0),
ctxFuncs: builtinFuncMap,
}, nil
p := Pagser{
Config: cfg,
//mapTags: make(map[string]*tagTokenizer, 0),
//mapFuncs: builtinFuncs,
}
for k, v := range builtinFuncs {
p.mapFuncs.Store(k, v)
}
return &p, nil
}
14 changes: 9 additions & 5 deletions parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,16 @@ func (p *Pagser) doParse(v interface{}, stackRefValues []reflect.Value, selectio
continue
}

tag, ok := p.ctxTags[tagValue]
if !ok || tag == nil {
cacheTag, ok := p.mapTags.Load(tagValue)
var tag *tagTokenizer
if !ok || cacheTag == nil {
tag, err = p.newTag(tagValue)
if err != nil {
return err
}
p.ctxTags[tagValue] = tag
p.mapTags.Store(tagValue, tag)
} else {
tag = cacheTag.(*tagTokenizer)
}

node := selection
Expand Down Expand Up @@ -201,8 +204,9 @@ func (p *Pagser) findAndExecFunc(objRefValue reflect.Value, stackRefValues []ref
}

//global function
if fn, ok := p.ctxFuncs[selTag.FuncName]; ok {
outValue, err := fn(node, selTag.FuncParams...)
if fn, ok := p.mapFuncs.Load(selTag.FuncName); ok {
cfn := fn.(CallFunc)
outValue, err := cfn(node, selTag.FuncParams...)
if err != nil {
return nil, fmt.Errorf("call registered func %v error: %v", selTag.FuncName, err)
}
Expand Down
21 changes: 21 additions & 0 deletions parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"net/http"
"strings"
"sync"
"testing"

"github.com/PuerkitoBio/goquery"
Expand Down Expand Up @@ -310,3 +311,23 @@ func TestPagser_ParseReader(t *testing.T) {
}
fmt.Printf("json: %v\n", prettyJson(data))
}

func TestPagser_RegisterFunc(t *testing.T) {
threads := 1000
p := New()
var wg sync.WaitGroup

for i := 0; i < threads; i++ {
wg.Add(1)
go func() {
for j := 0; j < 10; j++ {
for k, v := range builtinFuncs {
p.RegisterFunc(k, v)
}
}
wg.Done()
}()
}

wg.Wait()
}

0 comments on commit 7c0044d

Please sign in to comment.