Browse Source
final attempt
final attempt
on par with 1K sized object, but no so good with large ones the default http flow control is better than current implementation.tcp_read
Chris Lu
5 years ago
2 changed files with 122 additions and 15 deletions
@ -0,0 +1,98 @@ |
|||
package util |
|||
|
|||
import ( |
|||
"errors" |
|||
"sync" |
|||
"time" |
|||
|
|||
"github.com/chrislusf/seaweedfs/weed/glog" |
|||
) |
|||
|
|||
var ( |
|||
TimeoutErr = errors.New("timeout") |
|||
) |
|||
|
|||
// A bufferedChan implemented by a buffered channel
|
|||
type ResourcePool struct { |
|||
sync.Mutex |
|||
bufferedChan chan interface{} |
|||
poolSizeLimit int |
|||
inuse int |
|||
newFn func() (interface{}, error) |
|||
} |
|||
|
|||
func NewResourcePool(poolSizeLimit int, newFn func() (interface{}, error)) *ResourcePool { |
|||
p := &ResourcePool{ |
|||
poolSizeLimit: poolSizeLimit, |
|||
newFn: newFn, |
|||
bufferedChan: make(chan interface{}, poolSizeLimit), |
|||
} |
|||
return p |
|||
} |
|||
|
|||
func (p *ResourcePool) Size() int { |
|||
p.Lock() |
|||
defer p.Unlock() |
|||
return len(p.bufferedChan) + p.inuse |
|||
} |
|||
|
|||
func (p *ResourcePool) Free() int { |
|||
p.Lock() |
|||
defer p.Unlock() |
|||
return p.poolSizeLimit - p.inuse |
|||
} |
|||
|
|||
func (p *ResourcePool) Get(timeout time.Duration) (interface{}, error) { |
|||
d, err := p.get(timeout) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
if d == nil && p.newFn != nil { |
|||
var err error |
|||
d, err = p.newFn() |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
} |
|||
p.Lock() |
|||
defer p.Unlock() |
|||
p.inuse++ |
|||
return d, nil |
|||
} |
|||
|
|||
func (p *ResourcePool) Release(v interface{}) { |
|||
|
|||
p.Lock() |
|||
defer p.Unlock() |
|||
if p.inuse == 0 { |
|||
glog.V(0).Infof("released too many times?") |
|||
return |
|||
} |
|||
p.bufferedChan <- v |
|||
p.inuse-- |
|||
} |
|||
|
|||
func (p *ResourcePool) get(timeout time.Duration) (interface{}, error) { |
|||
|
|||
select { |
|||
case v := <-p.bufferedChan: |
|||
return v, nil |
|||
default: |
|||
} |
|||
|
|||
if p.Free() > 0 { |
|||
d, err := p.newFn() |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
return d, nil |
|||
} |
|||
|
|||
// wait for an freed item
|
|||
select { |
|||
case v := <-p.bufferedChan: |
|||
return v, nil |
|||
case <-time.After(timeout): |
|||
} |
|||
return nil, TimeoutErr |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue