JCC-CSScheduler/manager/internal/jobmgr/event_set.go

108 lines
2.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package jobmgr
import (
"context"
"errors"
"gitlink.org.cn/cloudream/common/pkgs/logger"
"sync"
"gitlink.org.cn/cloudream/common/pkgs/future"
"gitlink.org.cn/cloudream/common/utils/lo2"
)
type EventWaitCondition func(evt Event) bool
var ErrJobCancelled = errors.New("job cancelled")
type Event interface {
Noop()
}
type EventWaiter struct {
condition EventWaitCondition
future *future.SetValueFuture[Event]
}
type EventSet struct {
events []Event
waiters []EventWaiter
lock sync.Mutex
}
func NewEventSet() EventSet {
return EventSet{}
}
func (s *EventSet) Post(evt Event) {
s.lock.Lock() // 加锁保护事件集合
defer s.lock.Unlock() // 确保在函数结束时释放锁
// 遍历等待者列表查找匹配的等待者。如果找到从列表中移除并设置其future的值。
used := false // 标记当前事件是否已被使用(即是否唤醒了某个等待者)
for i, waiter := range s.waiters {
if waiter.condition(evt) { // 检查当前事件是否满足等待条件
s.waiters = lo2.RemoveAt(s.waiters, i) // 从等待者列表中移除当前等待者
waiter.future.SetValue(evt) // 设置等待者的future值为当前事件
used = true // 标记事件已被使用
}
}
// 如果没有匹配的等待者,则将事件添加到事件列表中。
if !used {
s.events = append(s.events, evt)
}
}
func (s *EventSet) Wait(ctx context.Context, cond EventWaitCondition) (Event, bool) {
s.lock.Lock()
for i, evt := range s.events {
if cond(evt) {
s.events = lo2.RemoveAt(s.events, i)
s.lock.Unlock()
return evt, true
}
}
fut := future.NewSetValue[Event]()
waiter := EventWaiter{
condition: cond,
future: fut,
}
s.waiters = append(s.waiters, waiter)
logger.Info("append waiter: %p", &waiter)
s.lock.Unlock()
val, err := fut.Wait(ctx)
if err != nil {
return nil, false
}
return val, true
}
func (s *EventSet) BeginWait(cond EventWaitCondition) future.Future1[Event] {
s.lock.Lock()
for i, evt := range s.events {
if cond(evt) {
s.events = lo2.RemoveAt(s.events, i)
s.lock.Unlock()
return future.NewReadyValue1(evt)
}
}
fut := future.NewSetValue[Event]()
waiter := EventWaiter{
condition: cond,
future: fut,
}
s.waiters = append(s.waiters, waiter)
s.lock.Unlock()
return fut
}