Skip to content

Commit

Permalink
pref(internal/tree): 缩小 locker 的使用范围
Browse files Browse the repository at this point in the history
  • Loading branch information
caixw committed May 22, 2024
1 parent ff156e5 commit d528b3c
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 35 deletions.
16 changes: 10 additions & 6 deletions internal/tree/bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (
"github.com/issue9/mux/v9/types"
)

func BenchmarkTree_Match(b *testing.B) {
func BenchmarkTree_Handler(b *testing.B) {
a := assert.New(b, false)
tree := NewTestTree(a, true, nil, syntax.NewInterceptors())

Expand Down Expand Up @@ -46,8 +46,10 @@ func BenchmarkTree_Match(b *testing.B) {
index := i % len(paths)
p := types.NewContext()
p.Path = paths[index]
h := tree.match(p)
a.True(len(h.handlers) > 0)
node, h, ok := tree.Handler(p, http.MethodGet)
a.True(ok).
NotNil(node).
NotNil(h)
}
}

Expand Down Expand Up @@ -81,13 +83,15 @@ func BenchmarkTree_ServeHTTP(b *testing.B) {
index := i % len(paths)
p := types.NewContext()
p.Path = paths[index]
h := tree.match(p)
hh := h.handlers[http.MethodGet]
node, h, ok := tree.Handler(p, http.MethodGet)
a.True(ok).
NotNil(node).
NotNil(h)

w := httptest.NewRecorder()
r, err := http.NewRequest(http.MethodGet, paths[index], nil)
a.NotError(err).NotNil(r)
hh.ServeHTTP(w, r)
h.ServeHTTP(w, r)
a.Equal(w.Result().StatusCode, index+201)
}
}
28 changes: 12 additions & 16 deletions internal/tree/tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,17 +212,13 @@ func (tree *Tree[T]) getNode(pattern string) (*node[T], error) {
return tree.node.getNode(segs)
}

// match 找到与路径 p.Path 匹配的 node 实例
func (tree *Tree[T]) match(p *types.Context) *node[T] {
if p.Path == "*" || p.Path == "" {
return tree.node
}

node := tree.node.matchChildren(p)
if node == nil || node.size() == 0 {
return nil
// 此方法主要用于将 locker 的使用范围减至最小。
func (tree *Tree[T]) match(ctx *types.Context) *node[T] {
if tree.locker != nil {
tree.locker.RLock()
defer tree.locker.RUnlock()
}
return node
return tree.node.matchChildren(ctx)
}

// Handler 查找与参数匹配的处理对象
Expand All @@ -235,16 +231,16 @@ func (tree *Tree[T]) Handler(ctx *types.Context, method string) (types.Node, T,
return tree.node, tree.trace, true
}

if tree.locker != nil {
tree.locker.RLock()
defer tree.locker.RUnlock()
var node *node[T]
if ctx.Path == "*" || ctx.Path == "" {
node = tree.node
} else {
node = tree.match(ctx)
}

node := tree.match(ctx)
if node == nil {
if node == nil || node.size() == 0 {
return nil, tree.notFound, false
}

if h, exists := node.handlers[method]; exists {
return node, h, true
}
Expand Down
31 changes: 18 additions & 13 deletions internal/tree/tree_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ func (t *tester) notFound(path string) {

ctx := types.NewContext()
ctx.Path = path
hs := t.tree.match(ctx)
t.a.Nil(hs).Zero(ctx.Count())
_, _, ok := t.tree.Handler(ctx, http.MethodOptions)
t.a.False(ok)
}

// 验证指定的路径返回的参数是否正确
Expand Down Expand Up @@ -121,11 +121,10 @@ func (t *tester) optionsTrue(path, options string) {

ctx := types.NewContext()
ctx.Path = path
hs := t.tree.match(ctx)
t.a.NotNil(hs)

h, exists := hs.handlers[http.MethodOptions]
t.a.NotNil(h).True(exists)
node, h, ok := t.tree.Handler(ctx, http.MethodOptions)
t.a.True(ok).
NotNil(node).
NotNil(h)

w := httptest.NewRecorder()
u, err := url.Parse(path)
Expand Down Expand Up @@ -587,12 +586,15 @@ func TestTree_match(t *testing.T) {

ctx := types.NewContext()
ctx.Path = "/path1"
node := tree.match(ctx)
a.Zero(ctx.Count()).NotNil(node)
node, h, ok := tree.Handler(ctx, http.MethodOptions)
a.True(ok).
NotNil(node).
NotNil(h).
Zero(ctx.Count())

w := httptest.NewRecorder()
r := rest.NewRequest(a, http.MethodOptions, "/path1").Request()
node.handlers[http.MethodOptions].ServeHTTP(w, r)
h.ServeHTTP(w, r)
a.Empty(w.Header().Get("h1")).
Equal(w.Header().Get(header.Allow), "GET, HEAD, OPTIONS").
Empty(w.Body.String())
Expand All @@ -610,12 +612,15 @@ func TestTree_match(t *testing.T) {

ctx = types.NewContext()
ctx.Path = "/path2"
node = tree.match(ctx)
a.Zero(ctx.Count()).NotNil(node)
node, h, ok = tree.Handler(ctx, http.MethodOptions)
a.True(ok).
NotNil(node).
NotNil(h).
Zero(ctx.Count())

w = httptest.NewRecorder()
r = rest.NewRequest(a, http.MethodOptions, "/path2").Request()
node.handlers[http.MethodOptions].ServeHTTP(w, r)
h.ServeHTTP(w, r)
a.Empty(w.Header().Get("h1")).
Equal(w.Header().Get(header.Allow), "GET, HEAD, OPTIONS").
Empty(w.Body.String())
Expand Down

0 comments on commit d528b3c

Please sign in to comment.