diff --git a/scanner/lexer.go b/scanner/lexer.go index 6f02ab1..0c43ec8 100644 --- a/scanner/lexer.go +++ b/scanner/lexer.go @@ -6,7 +6,6 @@ import ( "bytes" t "go/token" "io" - "sync" "unicode" "github.com/z7zmey/php-parser/position" @@ -36,7 +35,7 @@ type Lexer struct { Meta []meta.Meta heredocLabel string tokenBytesBuf *bytes.Buffer - TokenPool sync.Pool + TokenPool *TokenPool WithMeta bool lastToken *Token } @@ -74,9 +73,7 @@ func NewLexer(src io.Reader, fName string) *Lexer { Meta: nil, heredocLabel: "", tokenBytesBuf: &bytes.Buffer{}, - TokenPool: sync.Pool{ - New: func() interface{} { return &Token{} }, - }, + TokenPool: &TokenPool{}, } } @@ -123,7 +120,7 @@ func (l *Lexer) createToken(chars []lex.Char) *Token { firstChar := chars[0] lastChar := chars[len(chars)-1] - token := l.TokenPool.Get().(*Token) + token := l.TokenPool.Get() token.Meta = l.Meta token.Value = l.tokenString(chars) diff --git a/scanner/token_pool.go b/scanner/token_pool.go new file mode 100644 index 0000000..bad7986 --- /dev/null +++ b/scanner/token_pool.go @@ -0,0 +1,22 @@ +package scanner + +// TokenPool light version of sync.Pool for Token objects +type TokenPool struct { + pool []*Token +} + +// Get returns *Token from pool or creates new object +func (tp *TokenPool) Get() *Token { + if len(tp.pool) < 1 { + return new(Token) + } + + t := tp.pool[len(tp.pool)-1] + tp.pool = tp.pool[:len(tp.pool)-1] + return t +} + +// Put returns *Token to pool +func (tp *TokenPool) Put(t *Token) { + tp.pool = append(tp.pool, t) +} diff --git a/scanner/token_pool_test.go b/scanner/token_pool_test.go new file mode 100644 index 0000000..1d92d4f --- /dev/null +++ b/scanner/token_pool_test.go @@ -0,0 +1,34 @@ +package scanner_test + +import ( + "reflect" + "testing" + + "github.com/z7zmey/php-parser/scanner" +) + +func TestTokenPoolGetNew(t *testing.T) { + tp := new(scanner.TokenPool) + + newToken := tp.Get() + + if newToken == nil { + t.Errorf("*TokenPool.Get() must return new *Token object\n") + } +} + +func TestTokenPoolGetFromPool(t *testing.T) { + tp := new(scanner.TokenPool) + + expectedToken := &scanner.Token{ + Value: "test", + } + + tp.Put(expectedToken) + + actualToken := tp.Get() + + if !reflect.DeepEqual(expectedToken, actualToken) { + t.Errorf("*TokenPool.Put() must return *Token object from pool\n") + } +}