-
Notifications
You must be signed in to change notification settings - Fork 0
/
events.go
99 lines (87 loc) · 2.31 KB
/
events.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// SPDX-FileCopyrightText: 2019-2024 caixw
//
// SPDX-License-Identifier: MIT
// Package events 提供了简单的事件发布订阅功能
//
// e := events.New[string]()
//
// // 订阅事件
// e.Subscribe(func(data string){
// fmt.Println("subscriber 1:", data)
// })
//
// // 订阅事件
// e.Subscribe(func(data string){
// fmt.Println("subscriber 2:", data)
// })
//
// e.Publish(true, "test") // 发布事件
package events
import (
"context"
"reflect"
"github.com/puzpuzpuz/xsync/v3"
)
type (
// SubscribeFunc 订阅者函数
//
// data 为事件传递过来的数据,可能存在多个订阅者,
// 用户不应该直接修改 data 数据,否则结果是未知的。
SubscribeFunc[T any] func(data T)
// Publisher 事件的发布者
Publisher[T any] interface {
// Publish 触发事件
//
// sync 表示订阅者是否以异步的方式执行;
// data 传递给订阅者的数据;
Publish(sync bool, data T)
}
// Subscriber 供用户订阅事件的对象接口
Subscriber[T any] interface {
// Subscribe 注册订阅事件
//
// 返回用于注销此订阅事件的方法。
Subscribe(SubscribeFunc[T]) context.CancelFunc
}
// Event 事件处理对象
//
// 同时实现了 [Subscriber] 和 [Publisher] 两个接口。
Event[T any] struct {
subscribers *xsync.MapOf[uintptr, SubscribeFunc[T]]
}
)
// New 声明一个新的事件处理
//
// T 为事件传递过程的参数类型;
func New[T any]() *Event[T] {
return &Event[T]{
subscribers: xsync.NewMapOf[uintptr, SubscribeFunc[T]](),
}
}
func (e *Event[T]) Publish(sync bool, data T) {
if sync {
e.subscribers.Range(func(key uintptr, value SubscribeFunc[T]) bool {
go func(sub SubscribeFunc[T]) { sub(data) }(value)
return true
})
} else {
e.subscribers.Range(func(key uintptr, value SubscribeFunc[T]) bool {
value(data)
return true
})
}
}
func (e *Event[T]) Subscribe(subscriber SubscribeFunc[T]) context.CancelFunc {
ptr := reflect.ValueOf(subscriber).Pointer()
e.subscribers.Store(ptr, subscriber)
return func() { e.subscribers.Delete(ptr) }
}
// Reset 重置对象
func (e *Event[T]) Reset() {
e.subscribers.Range(func(key uintptr, _ SubscribeFunc[T]) bool {
e.subscribers.Delete(key)
return true
})
}
// Len 订阅者的数量
func (e *Event[T]) Len() (c int) { return e.subscribers.Size() }