From 9421819d7943356517f031d1832ea39ad50e9d75 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Tue, 12 Jul 2016 12:19:27 -0400 Subject: [PATCH] Add locking to patricia tree MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes race conditions in matchers. Impact on benchmarks: name old time/op new time/op delta CMuxConnHTTP1-4 664ns ±19% 849ns ± 6% +27.91% (p=0.000 n=9+10) CMuxConnHTTP2-4 745ns ±16% 699ns ± 9% ~ (p=0.075 n=9+10) CMuxConnHTTP1n2-4 930ns ±28% 1079ns ± 4% +16.00% (p=0.022 n=10+9) CMuxConnHTTP2n1-4 1.18µs ±52% 0.98µs ±13% ~ (p=1.000 n=10+10) name old alloc/op new alloc/op delta CMuxConnHTTP1-4 256B ± 0% 256B ± 0% ~ (all samples are equal) CMuxConnHTTP2-4 288B ± 0% 288B ± 0% ~ (all samples are equal) CMuxConnHTTP1n2-4 288B ± 0% 288B ± 0% ~ (all samples are equal) CMuxConnHTTP2n1-4 288B ± 0% 288B ± 0% ~ (all samples are equal) name old allocs/op new allocs/op delta CMuxConnHTTP1-4 3.00 ± 0% 3.00 ± 0% ~ (all samples are equal) CMuxConnHTTP2-4 4.00 ± 0% 4.00 ± 0% ~ (all samples are equal) CMuxConnHTTP1n2-4 4.00 ± 0% 4.00 ± 0% ~ (all samples are equal) CMuxConnHTTP2n1-4 4.00 ± 0% 4.00 ± 0% ~ (all samples are equal) --- patricia.go | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/patricia.go b/patricia.go index 0099e38..ec10514 100644 --- a/patricia.go +++ b/patricia.go @@ -17,13 +17,17 @@ package cmux import ( "bytes" "io" + "sync" ) // patriciaTree is a simple patricia tree that handles []byte instead of string // and cannot be changed after instantiation. type patriciaTree struct { root *ptNode - buf []byte // preallocated buffer to read data while matching + mu struct { + sync.Mutex + buf []byte // preallocated buffer to read data while matching + } } func newPatriciaTree(bs ...[]byte) *patriciaTree { @@ -33,10 +37,10 @@ func newPatriciaTree(bs ...[]byte) *patriciaTree { max = len(b) } } - return &patriciaTree{ - root: newNode(bs), - buf: make([]byte, max+1), - } + t := patriciaTree{root: newNode(bs)} + t.mu.buf = make([]byte, max+1) + + return &t } func newPatriciaTreeString(strs ...string) *patriciaTree { @@ -48,13 +52,19 @@ func newPatriciaTreeString(strs ...string) *patriciaTree { } func (t *patriciaTree) matchPrefix(r io.Reader) bool { - n, _ := io.ReadFull(r, t.buf) - return t.root.match(t.buf[:n], true) + t.mu.Lock() + defer t.mu.Unlock() + + n, _ := io.ReadFull(r, t.mu.buf) + return t.root.match(t.mu.buf[:n], true) } func (t *patriciaTree) match(r io.Reader) bool { - n, _ := io.ReadFull(r, t.buf) - return t.root.match(t.buf[:n], false) + t.mu.Lock() + defer t.mu.Unlock() + + n, _ := io.ReadFull(r, t.mu.buf) + return t.root.match(t.mu.buf[:n], false) } type ptNode struct {