|
- package event
-
- import (
- "sync"
-
- "github.com/zyedidia/generic/list"
- mysync "gitlink.org.cn/cloudream/common/utils/sync"
- )
-
- type ExecuteOption struct {
- IsEmergency bool
- DontMerge bool
- }
- type ExecuteContext[TArgs any] struct {
- Executor *Executor[TArgs]
- Option ExecuteOption
- Args TArgs
- }
- type postedEvent[TArgs any] struct {
- Event Event[TArgs]
- Option ExecuteOption
- }
-
- type Executor[TArgs any] struct {
- events *list.List[postedEvent[TArgs]]
- locker sync.Mutex
- eventCond *mysync.CounterCond
- execArgs TArgs
- }
-
- func NewExecutor[TArgs any](args TArgs) Executor[TArgs] {
- return Executor[TArgs]{
- events: list.New[postedEvent[TArgs]](),
- locker: sync.Mutex{},
- eventCond: mysync.NewCounterCond(0),
- execArgs: args,
- }
- }
-
- func (e *Executor[TArgs]) Post(event Event[TArgs], opts ...ExecuteOption) {
- opt := ExecuteOption{
- IsEmergency: false,
- DontMerge: false,
- }
-
- if len(opts) > 0 {
- opt = opts[0]
- }
-
- e.locker.Lock()
- defer e.locker.Unlock()
-
- // 紧急任务直接插入到队头,不进行合并
- if opt.IsEmergency {
- e.events.PushFront(postedEvent[TArgs]{
- Event: event,
- Option: opt,
- })
- e.eventCond.Release()
- return
- }
-
- // 合并任务
- if opt.DontMerge {
- ptr := e.events.Front
- for ptr != nil {
- // 只与非紧急任务,且允许合并的任务进行合并
- if !ptr.Value.Option.IsEmergency && !ptr.Value.Option.DontMerge {
- if ptr.Value.Event.TryMerge(event) {
- return
- }
- }
-
- ptr = ptr.Next
- }
- }
-
- e.events.PushBack(postedEvent[TArgs]{
- Event: event,
- Option: opt,
- })
- e.eventCond.Release()
- }
-
- // Execute 开始执行任务
- func (e *Executor[TArgs]) Execute() error {
- for {
- e.eventCond.Wait()
-
- event := e.popFrontEvent()
- if event == nil {
- continue
- }
-
- ctx := ExecuteContext[TArgs]{
- Executor: e,
- Option: event.Option,
- Args: e.execArgs,
- }
-
- event.Event.Execute(ctx)
- }
- }
-
- func (e *Executor[TArgs]) popFrontEvent() *postedEvent[TArgs] {
- e.locker.Lock()
- defer e.locker.Unlock()
-
- if e.events.Front == nil {
- return nil
- }
-
- return &e.events.Front.Value
- }
|