Files
gf/g/container/gpool/gpool.go

115 lines
3.3 KiB
Go
Raw Normal View History

// 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表示超时回收
2018-07-21 15:23:16 +08:00
// 注意过期时间单位为**毫秒**
func New(expire int, newFunc...func() (interface{}, error)) *Pool {
r := &Pool {
list : glist.New(),
closed : gtype.NewBool(),
2018-07-12 20:32:56 +08:00
Expire : int64(expire),
}
if len(newFunc) > 0 {
2018-07-12 20:32:56 +08:00
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)
2018-08-16 18:17:47 +08:00
if f.expire == 0 || f.expire > gtime.Millisecond() {
return f.value, nil
}
} else {
break
}
}
2018-07-12 20:32:56 +08:00
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() {
2018-07-21 15:23:16 +08:00
for {
if r := p.list.PopFront(); r != nil {
item := r.(*poolItem)
2018-08-16 18:17:47 +08:00
if item.expire == 0 || item.expire > gtime.Millisecond() {
p.list.PushFront(item)
2018-07-21 15:23:16 +08:00
break
}
if p.ExpireFunc != nil {
p.ExpireFunc(item.value)
}
} else {
break
}
}
2018-07-21 15:23:16 +08:00
time.Sleep(time.Second)
}
}