2
0

Add Resource.Hijack

This commit is contained in:
Jack Christensen
2018-12-26 13:01:31 -06:00
parent af5402c2dd
commit 7df4afe7d3
2 changed files with 46 additions and 0 deletions
+27
View File
@@ -10,6 +10,7 @@ const (
resourceStatusCreating = 0
resourceStatusAvailable = iota
resourceStatusBorrowed = iota
resourceStatusHijacked = iota
)
const maxUint = ^uint(0)
@@ -32,13 +33,28 @@ func (res *Resource) Value() interface{} {
}
func (res *Resource) Release() {
if res.status != resourceStatusBorrowed {
panic("tried to release resource that is not acquired")
}
res.pool.releaseBorrowedResource(res)
}
func (res *Resource) Destroy() {
if res.status != resourceStatusBorrowed {
panic("tried to destroy resource that is not acquired")
}
res.pool.destroyBorrowedResource(res)
}
// Hijack removes the resource from the pool without destroying it. Caller is
// responsible for cleanup of resource value.
func (res *Resource) Hijack() {
if res.status != resourceStatusBorrowed {
panic("tried to hijack resource that is not acquired")
}
res.pool.hijackBorrowedResource(res)
}
// Pool is a thread-safe resource pool.
type Pool struct {
cond *sync.Cond
@@ -244,6 +260,17 @@ func (p *Pool) destroyBorrowedResource(res *Resource) {
p.cond.Signal()
}
func (p *Pool) hijackBorrowedResource(res *Resource) {
p.cond.L.Lock()
p.allResources = removeResource(p.allResources, res)
res.status = resourceStatusHijacked
p.destructWG.Done() // not responsible for destructing hijacked resources
p.cond.L.Unlock()
p.cond.Signal()
}
func removeResource(slice []*Resource, res *Resource) []*Resource {
for i := range slice {
if slice[i] == res {
+19
View File
@@ -264,6 +264,25 @@ func TestPoolCloseBlocksUntilAllResourcesReleasedAndClosed(t *testing.T) {
}
func TestResourceDestroyRemovesResourceFromPool(t *testing.T) {
createFunc, _ := createCreateResourceFunc()
var closeCalls Counter
closeFunc := func(interface{}) {
closeCalls.Next()
}
pool := puddle.NewPool(createFunc, closeFunc)
res, err := pool.Acquire(context.Background())
require.NoError(t, err)
assert.Equal(t, 1, res.Value())
res.Hijack()
assert.Equal(t, 0, pool.Size())
assert.Equal(t, 0, closeCalls.Value())
}
func TestResourceHijackRemovesResourceFromPoolButDoesNotDestroy(t *testing.T) {
createFunc, _ := createCreateResourceFunc()
pool := puddle.NewPool(createFunc, stubCloseRes)