91 lines
2.1 KiB
Go
91 lines
2.1 KiB
Go
package jobmgr
|
||
|
||
import (
|
||
"context"
|
||
"errors"
|
||
"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{}
|
||
}
|
||
|
||
// Post 函数用于向事件集合中发布一个事件。
|
||
// 如果有等待该事件的协程,会唤醒它们并将事件传递给它们。
|
||
// 参数:
|
||
//
|
||
// evt Event - 需要发布的事件对象。
|
||
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()
|
||
//defer s.lock.Unlock()
|
||
|
||
// 一个等待者只能等待一个事件
|
||
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.events = append(s.events, waiter)
|
||
s.waiters = append(s.waiters, waiter)
|
||
|
||
s.lock.Unlock()
|
||
|
||
val, err := fut.WaitValue(ctx)
|
||
|
||
if err != nil {
|
||
return nil, false
|
||
}
|
||
|
||
return val, true
|
||
}
|