go-ethereum/rpc/execution_pool.go
2023-09-11 11:58:40 +05:30

99 lines
1.4 KiB
Go

package rpc
import (
"context"
"sync"
"sync/atomic"
"time"
"github.com/JekaMas/workerpool"
)
type SafePool struct {
executionPool *atomic.Pointer[workerpool.WorkerPool]
sync.RWMutex
timeout time.Duration
size int
// Skip sending task to execution pool
fastPath bool
}
func NewExecutionPool(initialSize int, timeout time.Duration) *SafePool {
sp := &SafePool{
size: initialSize,
timeout: timeout,
}
if initialSize == 0 {
sp.fastPath = true
return sp
}
var ptr atomic.Pointer[workerpool.WorkerPool]
p := workerpool.New(initialSize)
ptr.Store(p)
sp.executionPool = &ptr
return sp
}
func (s *SafePool) Submit(ctx context.Context, fn func() error) (<-chan error, bool) {
if s.fastPath {
go func() {
_ = fn()
}()
return nil, true
}
if s.executionPool == nil {
return nil, false
}
pool := s.executionPool.Load()
if pool == nil {
return nil, false
}
return pool.Submit(ctx, fn, s.Timeout()), true
}
func (s *SafePool) ChangeSize(n int) {
oldPool := s.executionPool.Swap(workerpool.New(n))
if oldPool != nil {
go func() {
oldPool.StopWait()
}()
}
s.Lock()
s.size = n
s.Unlock()
}
func (s *SafePool) ChangeTimeout(n time.Duration) {
s.Lock()
defer s.Unlock()
s.timeout = n
}
func (s *SafePool) Timeout() time.Duration {
s.RLock()
defer s.RUnlock()
return s.timeout
}
func (s *SafePool) Size() int {
s.RLock()
defer s.RUnlock()
return s.size
}