1
0
mirror of https://github.com/pocketbase/pocketbase.git synced 2024-12-03 19:26:50 +02:00
pocketbase/plugins/jsvm/pool.go
2023-07-08 13:51:16 +03:00

74 lines
1.4 KiB
Go

package jsvm
import (
"sync"
"github.com/dop251/goja"
)
type poolItem struct {
mux sync.Mutex
busy bool
vm *goja.Runtime
}
type vmsPool struct {
mux sync.RWMutex
factory func() *goja.Runtime
items []*poolItem
}
// newPool creates a new pool with pre-warmed vms generated from the specified factory.
func newPool(size int, factory func() *goja.Runtime) *vmsPool {
pool := &vmsPool{
factory: factory,
items: make([]*poolItem, size),
}
for i := 0; i < size; i++ {
vm := pool.factory()
pool.items[i] = &poolItem{vm: vm}
}
return pool
}
// run executes "call" with a vm created from the pool
// (either from the buffer or a new one if all buffered vms are busy)
func (p *vmsPool) run(call func(vm *goja.Runtime) error) error {
p.mux.RLock()
// try to find a free item
var freeItem *poolItem
for _, item := range p.items {
item.mux.Lock()
if item.busy {
item.mux.Unlock()
continue
}
item.busy = true
item.mux.Unlock()
freeItem = item
break
}
p.mux.RUnlock()
// create a new one-off item if of all of the pool items are currently busy
//
// note: if turned out not efficient we may change this in the future
// by adding the created item in the pool with some timer for removal
if freeItem == nil {
return call(p.factory())
}
execErr := call(freeItem.vm)
// "free" the vm
freeItem.mux.Lock()
freeItem.busy = false
freeItem.mux.Unlock()
return execErr
}