Browse Source

Task改名成Event

pull/1/head
Sydonian 2 years ago
parent
commit
dbf26d4489
4 changed files with 153 additions and 1 deletions
  1. +1
    -1
      consts/event/event.go
  2. +6
    -0
      pkg/event/event.go
  3. +114
    -0
      pkg/event/executor.go
  4. +32
    -0
      utils/sync/counter_cond.go

consts/task/task.go → consts/event/event.go View File

@@ -1,4 +1,4 @@
package task
package event


const ( const (
UPDATE_CACHE_OP_UNTEMP = "UnTemp" UPDATE_CACHE_OP_UNTEMP = "UnTemp"

+ 6
- 0
pkg/event/event.go View File

@@ -0,0 +1,6 @@
package event

type Event[TArgs any] interface {
TryMerge(other Event[TArgs]) bool // 尝试将other任务与自身合并,如果成功返回true
Execute(ctx ExecuteContext[TArgs])
}

+ 114
- 0
pkg/event/executor.go View File

@@ -0,0 +1,114 @@
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
}

+ 32
- 0
utils/sync/counter_cond.go View File

@@ -0,0 +1,32 @@
package sync

import "sync"

type CounterCond struct {
count int
cond *sync.Cond
}

func NewCounterCond(initCount int) *CounterCond {
return &CounterCond{
count: initCount,
cond: sync.NewCond(&sync.Mutex{}),
}
}

func (c *CounterCond) Wait() {
c.cond.L.Lock()

for c.count == 0 {
c.cond.Wait()
}

c.count--

c.cond.L.Unlock()
}

func (c *CounterCond) Release() {
c.count++
c.cond.Signal()
}

Loading…
Cancel
Save