// New returns a new Pool structure. func New(setters ...Configurator) (*Pool, error) { pc := &config{ size: DefaultSize, } for _, setter := range setters { if err := setter(pc); err != nil { return nil, err } } if pc.address == "" { return nil, errors.New("cannot create pool with empty address") } pool, err := gopool.New( gopool.Size(pc.size), gopool.Close(func(conn interface{}) error { return conn.(io.ReadWriteCloser).Close() }), gopool.Factory(func() (interface{}, error) { if pc.printer != nil { return goperconn.New(goperconn.Address(pc.address), goperconn.Logger(pc.printer)) } return goperconn.New(goperconn.Address(pc.address)) }), ) if err != nil { return nil, err } return &Pool{pool: pool}, nil }
func main() { const iterationCount = 1000 const parallelCount = 100 makeBuffer := func() (interface{}, error) { return bytes.NewBuffer(make([]byte, 0, bufSize)), nil } resetBuffer := func(item interface{}) { item.(*bytes.Buffer).Reset() } bp, err := gopool.New(gopool.Size(poolSize), gopool.Factory(makeBuffer), gopool.Reset(resetBuffer)) if err != nil { log.Fatal(err) } var wg sync.WaitGroup wg.Add(parallelCount) for i := 0; i < parallelCount; i++ { go func() { defer wg.Done() for j := 0; j < iterationCount; j++ { if err := grabBufferAndUseIt(bp); err != nil { fmt.Println(err) return } } }() } wg.Wait() }
func TestChanPool(t *testing.T) { pool, err := gopool.New(gopool.Factory(makeBuffer), gopool.Reset(resetBuffer), gopool.Close(closeBuffer)) if err != nil { t.Fatalf("Actual: %#v; Expected: %#v", err, nil) } test(t, pool) }
func TestChanPoolErrorWithNonPositiveSize(t *testing.T) { pool, err := gopool.New(gopool.Size(0)) if pool != nil { t.Errorf("Actual: %#v; Expected: %#v", pool, nil) } if err == nil { t.Errorf("Actual: %#v; Expected: %#v", err, "not nil") } pool, err = gopool.New(gopool.Size(-1)) if pool != nil { t.Errorf("Actual: %#v; Expected: %#v", pool, nil) } if err == nil { t.Errorf("Actual: %#v; Expected: %#v", err, "not nil") } }
func TestChanPoolErrorWithoutFactory(t *testing.T) { pool, err := gopool.New() if pool != nil { t.Errorf("Actual: %#v; Expected: %#v", pool, nil) } if err == nil { t.Errorf("Actual: %#v; Expected: %#v", err, "not nil") } }
func TestChanPoolCreatesSizeItems(t *testing.T) { var size = 42 var factoryInvoked int _, err := gopool.New(gopool.Size(size), gopool.Factory(func() (interface{}, error) { factoryInvoked++ return nil, nil })) if err != nil { t.Fatal(err) } if actual, expected := factoryInvoked, size; actual != expected { t.Errorf("Actual: %#v; Expected: %#v", actual, expected) } }
func TestChanPoolInvokesReset(t *testing.T) { var resetInvoked int pool, err := gopool.New( gopool.Factory(func() (interface{}, error) { return nil, nil }), gopool.Reset(func(item interface{}) { resetInvoked++ })) if err != nil { t.Fatal(err) } pool.Put(pool.Get()) if actual, expected := resetInvoked, 1; actual != expected { t.Errorf("Actual: %#v; Expected: %#v", actual, expected) } }
func TestChanPoolInvokesClose(t *testing.T) { var closeInvoked int pool, err := gopool.New(gopool.Size(1), gopool.Factory(func() (interface{}, error) { return nil, nil }), gopool.Close(func(_ interface{}) error { closeInvoked++ return errors.New("foo") })) if err != nil { t.Fatal(err) } if err := pool.Close(); err == nil || err.Error() != "foo" { t.Errorf("Actual: %#v; Expected: %#v", err, "foo") } if actual, expected := closeInvoked, 1; actual != expected { t.Errorf("Actual: %#v; Expected: %#v", actual, expected) } }
func BenchmarkChanHighConcurrency(b *testing.B) { pool, _ := gopool.New(gopool.Factory(makeBuffer), gopool.Reset(resetBuffer), gopool.Close(closeBuffer), gopool.Size(10000)) bench(b, pool, highConcurrency) }