From 5ff780891e229dbde00d9a37c2f8b6681e592fdb Mon Sep 17 00:00:00 2001 From: Andrei Vagin Date: Thu, 6 Feb 2020 10:06:56 -0800 Subject: Move p9.pool to a separate package PiperOrigin-RevId: 293617493 --- pkg/pool/BUILD | 25 +++++++++++++++++++ pkg/pool/pool.go | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++ pkg/pool/pool_test.go | 64 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 155 insertions(+) create mode 100644 pkg/pool/BUILD create mode 100644 pkg/pool/pool.go create mode 100644 pkg/pool/pool_test.go (limited to 'pkg/pool') diff --git a/pkg/pool/BUILD b/pkg/pool/BUILD new file mode 100644 index 000000000..7b1c6b75b --- /dev/null +++ b/pkg/pool/BUILD @@ -0,0 +1,25 @@ +load("//tools:defs.bzl", "go_library", "go_test") + +package( + default_visibility = ["//visibility:public"], + licenses = ["notice"], +) + +go_library( + name = "pool", + srcs = [ + "pool.go", + ], + deps = [ + "//pkg/sync", + ], +) + +go_test( + name = "pool_test", + size = "small", + srcs = [ + "pool_test.go", + ], + library = ":pool", +) diff --git a/pkg/pool/pool.go b/pkg/pool/pool.go new file mode 100644 index 000000000..a1b2e0cfe --- /dev/null +++ b/pkg/pool/pool.go @@ -0,0 +1,66 @@ +// Copyright 2018 The gVisor Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package pool + +import ( + "gvisor.dev/gvisor/pkg/sync" +) + +// Pool is a simple allocator. +type Pool struct { + mu sync.Mutex + + // cache is the set of returned values. + cache []uint64 + + // Start is the starting value (if needed). + Start uint64 + + // max is the current maximum issued. + max uint64 + + // Limit is the upper limit. + Limit uint64 +} + +// Get gets a value from the pool. +func (p *Pool) Get() (uint64, bool) { + p.mu.Lock() + defer p.mu.Unlock() + + // Anything cached? + if len(p.cache) > 0 { + v := p.cache[len(p.cache)-1] + p.cache = p.cache[:len(p.cache)-1] + return v, true + } + + // Over the limit? + if p.Start == p.Limit { + return 0, false + } + + // Generate a new value. + v := p.Start + p.Start++ + return v, true +} + +// Put returns a value to the pool. +func (p *Pool) Put(v uint64) { + p.mu.Lock() + p.cache = append(p.cache, v) + p.mu.Unlock() +} diff --git a/pkg/pool/pool_test.go b/pkg/pool/pool_test.go new file mode 100644 index 000000000..d928439c1 --- /dev/null +++ b/pkg/pool/pool_test.go @@ -0,0 +1,64 @@ +// Copyright 2018 The gVisor Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package pool + +import ( + "testing" +) + +func TestPoolUnique(t *testing.T) { + p := Pool{Start: 1, Limit: 3} + got := make(map[uint64]bool) + + for { + n, ok := p.Get() + if !ok { + break + } + + // Check unique. + if _, ok := got[n]; ok { + t.Errorf("pool spit out %v multiple times", n) + } + + // Record. + got[n] = true + } +} + +func TestExausted(t *testing.T) { + p := Pool{Start: 1, Limit: 500} + for i := 0; i < 499; i++ { + _, ok := p.Get() + if !ok { + t.Fatalf("pool exhausted before 499 items") + } + } + + _, ok := p.Get() + if ok { + t.Errorf("pool not exhausted when it should be") + } +} + +func TestPoolRecycle(t *testing.T) { + p := Pool{Start: 1, Limit: 500} + n1, _ := p.Get() + p.Put(n1) + n2, _ := p.Get() + if n1 != n2 { + t.Errorf("pool not recycling items") + } +} -- cgit v1.2.3