Skip to content

Commit

Permalink
Added AcquireArgs and ReleaseArgs helper functions
Browse files Browse the repository at this point in the history
  • Loading branch information
valyala committed Feb 19, 2016
1 parent ed7ca4c commit 5a26dcc
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 2 deletions.
23 changes: 23 additions & 0 deletions args.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,31 @@ import (
"bytes"
"errors"
"io"
"sync"
)

// AcquireArgs returns an empty Args object from the pool.
//
// The returned Args may be returned to the pool with ReleaseArgs
// when no longer needed. This allows reducing GC load.
func AcquireArgs() *Args {
return argsPool.Get().(*Args)
}

// ReleaseArgs returns the object acquired via AquireArgs to the pool.
//
// Do not access the released Args object, otherwise data races may occur.
func ReleaseArgs(a *Args) {
a.Reset()
argsPool.Put(a)
}

var argsPool = &sync.Pool{
New: func() interface{} {
return &Args{}
},
}

// Args represents query arguments.
//
// It is forbidden copying Args instances. Create new instances instead
Expand Down
49 changes: 48 additions & 1 deletion args_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,56 @@ import (
"reflect"
"strings"
"testing"
"time"
)

func TestPeekMulti(t *testing.T) {
func TestArgsAcquireReleaseSequential(t *testing.T) {
testArgsAcquireRelease(t)
}

func TestArgsAcquireReleaseConcurrent(t *testing.T) {
ch := make(chan struct{}, 10)
for i := 0; i < 10; i++ {
go func() {
testArgsAcquireRelease(t)
ch <- struct{}{}
}()
}
for i := 0; i < 10; i++ {
select {
case <-ch:
case <-time.After(time.Second):
t.Fatalf("timeout")
}
}
}

func testArgsAcquireRelease(t *testing.T) {
a := AcquireArgs()

for i := 0; i < 10; i++ {
k := fmt.Sprintf("key_%d", i)
v := fmt.Sprintf("value_%d", i*3+123)
a.Set(k, v)
}

s := a.String()
a.Reset()
a.Parse(s)

for i := 0; i < 10; i++ {
k := fmt.Sprintf("key_%d", i)
expectedV := fmt.Sprintf("value_%d", i*3+123)
v := a.Peek(k)
if string(v) != expectedV {
t.Fatalf("unexpected value %q for key %q. Expecting %q", v, k, expectedV)
}
}

ReleaseArgs(a)
}

func TestArgsPeekMulti(t *testing.T) {
var a Args
a.Parse("foo=123&bar=121&foo=321&foo=&barz=sdf")

Expand Down
1 change: 1 addition & 0 deletions uri.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
// AcquireURI returns an empty URI instance from the pool.
//
// Release the URI with ReleaseURI after the URI is no longer needed.
// This allows reducing GC load.
func AcquireURI() *URI {
return uriPool.Get().(*URI)
}
Expand Down
2 changes: 1 addition & 1 deletion uri_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ func TestURIAcquireReleaseSequential(t *testing.T) {
}

func TestURIAcquireReleaseConcurrent(t *testing.T) {
ch := make(chan struct{})
ch := make(chan struct{}, 10)
for i := 0; i < 10; i++ {
go func() {
testURIAcquireRelease(t)
Expand Down

0 comments on commit 5a26dcc

Please sign in to comment.