mirror of
https://gitee.com/johng/gf
synced 2026-06-29 18:41:50 +08:00
115 lines
3.3 KiB
Go
115 lines
3.3 KiB
Go
// Copyright 2018 gf Author(https://gitee.com/johng/gf). All Rights Reserved.
|
||
//
|
||
// This Source Code Form is subject to the terms of the MIT License.
|
||
// If a copy of the MIT was not distributed with this file,
|
||
// You can obtain one at https://gitee.com/johng/gf.
|
||
|
||
// 对象复用池.
|
||
package gpool
|
||
|
||
import (
|
||
"time"
|
||
"errors"
|
||
"gitee.com/johng/gf/g/os/gtime"
|
||
"gitee.com/johng/gf/g/container/glist"
|
||
"gitee.com/johng/gf/g/container/gtype"
|
||
)
|
||
|
||
// 对象池
|
||
type Pool struct {
|
||
list *glist.List // 可用/闲置的文件指针链表
|
||
closed *gtype.Bool // 连接池是否已关闭
|
||
Expire int64 // (毫秒)闲置最大时间,超过该时间则被系统回收
|
||
NewFunc func()(interface{}, error) // 创建对象的方法定义
|
||
ExpireFunc func(interface{}) // 对象的过期销毁方法(当池对象销毁需要执行额外的销毁操作时,需要定义该方法)
|
||
// 例如: net.Conn, os.File等对象都需要执行额外关闭操作
|
||
}
|
||
|
||
// 对象池数据项
|
||
type poolItem struct {
|
||
expire int64 // (毫秒)过期时间
|
||
value interface{} // 对象值
|
||
}
|
||
|
||
// 创建一个对象池,为保证执行效率,过期时间一旦设定之后无法修改
|
||
// expire = 0表示不过期,expire < 0表示使用完立即回收,expire > 0表示超时回收
|
||
// 注意过期时间单位为**毫秒**
|
||
func New(expire int, newFunc...func() (interface{}, error)) *Pool {
|
||
r := &Pool {
|
||
list : glist.New(),
|
||
closed : gtype.NewBool(),
|
||
Expire : int64(expire),
|
||
}
|
||
if len(newFunc) > 0 {
|
||
r.NewFunc = newFunc[0]
|
||
}
|
||
go r.expireCheckingLoop()
|
||
return r
|
||
}
|
||
|
||
// 设置对象过期销毁时的关闭方法
|
||
func (p *Pool) SetExpireFunc(expireFunc func(interface{})) {
|
||
p.ExpireFunc = expireFunc
|
||
}
|
||
|
||
// 放一个临时对象到池中
|
||
func (p *Pool) Put(value interface{}) {
|
||
item := &poolItem {
|
||
value : value,
|
||
}
|
||
if p.Expire == 0 {
|
||
item.expire = 0
|
||
} else {
|
||
item.expire = gtime.Millisecond() + p.Expire
|
||
}
|
||
p.list.PushBack(item)
|
||
}
|
||
|
||
// 从池中获得一个临时对象
|
||
func (p *Pool) Get() (interface{}, error) {
|
||
for !p.closed.Val() {
|
||
if r := p.list.PopFront(); r != nil {
|
||
f := r.(*poolItem)
|
||
if f.expire == 0 || f.expire > gtime.Millisecond() {
|
||
return f.value, nil
|
||
}
|
||
} else {
|
||
break
|
||
}
|
||
}
|
||
if p.NewFunc != nil {
|
||
return p.NewFunc()
|
||
}
|
||
return nil, errors.New("pool is empty")
|
||
}
|
||
|
||
// 查询当前池中的对象数量
|
||
func (p *Pool) Size() int {
|
||
return p.list.Len()
|
||
}
|
||
|
||
// 关闭池
|
||
func (p *Pool) Close() {
|
||
p.closed.Set(true)
|
||
}
|
||
|
||
// 超时检测循环
|
||
func (p *Pool) expireCheckingLoop() {
|
||
for !p.closed.Val() {
|
||
for {
|
||
if r := p.list.PopFront(); r != nil {
|
||
item := r.(*poolItem)
|
||
if item.expire == 0 || item.expire > gtime.Millisecond() {
|
||
p.list.PushFront(item)
|
||
break
|
||
}
|
||
if p.ExpireFunc != nil {
|
||
p.ExpireFunc(item.value)
|
||
}
|
||
} else {
|
||
break
|
||
}
|
||
}
|
||
time.Sleep(time.Second)
|
||
}
|
||
} |