mirror of
https://github.com/pocketbase/pocketbase.git
synced 2024-12-11 05:11:13 +02:00
74 lines
1.4 KiB
Go
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
|
|
}
|