mirror of
https://github.com/crazybber/awesome-patterns.git
synced 2024-11-25 14:26:04 +03:00
initialize the pool patterns
This commit is contained in:
parent
ecef7a4803
commit
f57dd8dad4
90
concurrency/pool/main.go
Normal file
90
concurrency/pool/main.go
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Pool manages a set of resources that can be shared safely by
|
||||||
|
// multiply goroutines. The resource been managed must implement
|
||||||
|
// the io.Closer interface.
|
||||||
|
type Pool struct {
|
||||||
|
m sync.Mutex
|
||||||
|
resources chan io.Closer
|
||||||
|
factory func() (io.Closer, error)
|
||||||
|
closed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrPoolClosed is returned when an Acquire returns on a closed pool.
|
||||||
|
var ErrPoolClosed = errors.New("Pool has been closed")
|
||||||
|
|
||||||
|
// New creates a pool that manage resources. A pool requires a function
|
||||||
|
// that can allocate a new resource and the size of the pool.
|
||||||
|
func New(fn func() (io.Closer, error), size uint32) (*Pool, error) {
|
||||||
|
if size <= 0 {
|
||||||
|
return nil, errors.New("Size value too small")
|
||||||
|
}
|
||||||
|
return &Pool{
|
||||||
|
factory: fn,
|
||||||
|
resources: make(chan io.Closer, size),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Acquire retrieves a resource from the pool.
|
||||||
|
func (p *Pool) Acquire() (io.Closer, error) {
|
||||||
|
select {
|
||||||
|
// Check for free resources
|
||||||
|
case r, ok := <-p.resources:
|
||||||
|
if !ok {
|
||||||
|
return nil, ErrPoolClosed
|
||||||
|
}
|
||||||
|
log.Println("Aquire: ", "Shared Resource")
|
||||||
|
return r, nil
|
||||||
|
default:
|
||||||
|
log.Println("Aquire: ", "New Resource")
|
||||||
|
return p.factory()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release place a new resource into the pool.
|
||||||
|
func (p *Pool) Release(r io.Closer) {
|
||||||
|
// Secure this operation with the Close operation.
|
||||||
|
p.m.Lock()
|
||||||
|
defer p.m.Unlock()
|
||||||
|
// If the pool is closed, discard the resource
|
||||||
|
if p.closed {
|
||||||
|
r.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
// Attempt to place the new resource on the queue
|
||||||
|
case p.resources <- r:
|
||||||
|
log.Println("Release: ", "In Queue")
|
||||||
|
default:
|
||||||
|
// If the queue is already at capacity we close the resource
|
||||||
|
log.Println("Release:", "Closing")
|
||||||
|
r.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close will shutdown the pool and close all existing resources.
|
||||||
|
func (p *Pool) Close() {
|
||||||
|
// Secure this operation with release operation.
|
||||||
|
p.m.Lock()
|
||||||
|
defer p.m.Unlock()
|
||||||
|
// If the pool is already closed, do not do anything.
|
||||||
|
if p.closed {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// set the pool as closed.
|
||||||
|
p.closed = true
|
||||||
|
// Close the channel before we drain the channel of its
|
||||||
|
// resources
|
||||||
|
close(p.resources)
|
||||||
|
// Close the resources
|
||||||
|
for r := range p.resources {
|
||||||
|
r.Close()
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user