Add Resource.Hijack
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user