diff --git a/events.go b/events.go index 3ec02ff..e55725f 100644 --- a/events.go +++ b/events.go @@ -25,64 +25,70 @@ import ( "sync" ) -// SubscribeFunc 订阅者函数 -// -// data 为事件传递过来的数据,可能存在多个订阅者, -// 用户不应该直接修改 data 数据,否则结果是未知的。 -type SubscribeFunc[T any] func(data T) +type ( + // SubscribeFunc 订阅者函数 + // + // data 为事件传递过来的数据,可能存在多个订阅者, + // 用户不应该直接修改 data 数据,否则结果是未知的。 + SubscribeFunc[T any] func(data T) -type event[T any] struct { - funcs *sync.Map -} + // Publisher 事件的发布者 + Publisher[T any] interface { + // Publish 触发事件 + // + // sync 表示订阅者是否以异步的方式执行; + // data 传递给订阅者的数据; + Publish(sync bool, data T) + } -// Publisher 事件的发布者 -type Publisher[T any] interface { - // Publish 触发事件 - // - // sync 表示订阅者是否以异步的方式执行; - // data 传递给订阅者的数据; - Publish(sync bool, data T) -} + // Subscriber 供用户订阅事件的对象接口 + Subscriber[T any] interface { + // Subscribe 注册订阅事件 + // + // 返回用于注销此订阅事件的方法。 + Subscribe(SubscribeFunc[T]) context.CancelFunc + } -// Subscriber 供用户订阅事件的对象接口 -type Subscriber[T any] interface { - // Subscribe 注册订阅事件 + // Event 事件处理对象 // - // 返回用于注销此订阅事件的方法。 - Subscribe(SubscribeFunc[T]) (context.CancelFunc, error) -} - -type Eventer[T any] interface { - Publisher[T] - Subscriber[T] -} + // 同时实现了 [Subscriber] 和 [Publisher] 两个接口。 + Event[T any] struct { + subscribers *sync.Map + } +) // New 声明一个新的事件处理 // // T 为事件传递过程的参数类型; -func New[T any]() Eventer[T] { - return &event[T]{ - funcs: &sync.Map{}, +func New[T any]() *Event[T] { + return &Event[T]{ + subscribers: &sync.Map{}, } } -func (e *event[T]) Publish(sync bool, data T) { +func (e *Event[T]) Publish(sync bool, data T) { if sync { - e.funcs.Range(func(key, value any) bool { + e.subscribers.Range(func(key, value any) bool { go func(sub SubscribeFunc[T]) { sub(data) }(value.(SubscribeFunc[T])) return true }) } else { - e.funcs.Range(func(key, value any) bool { + e.subscribers.Range(func(key, value any) bool { value.(SubscribeFunc[T])(data) return true }) } } -func (e *event[T]) Subscribe(subscriber SubscribeFunc[T]) (context.CancelFunc, error) { +func (e *Event[T]) Subscribe(subscriber SubscribeFunc[T]) context.CancelFunc { ptr := reflect.ValueOf(subscriber).Pointer() - e.funcs.Store(ptr, subscriber) + e.subscribers.Store(ptr, subscriber) + return func() { e.subscribers.Delete(ptr) } +} - return func() { e.funcs.Delete(ptr) }, nil +func (e *Event[T]) Reset() { + e.subscribers.Range(func(key, _ any) bool { + e.subscribers.Delete(key) + return true + }) } diff --git a/events_test.go b/events_test.go index d2f88c9..08a452f 100644 --- a/events_test.go +++ b/events_test.go @@ -13,15 +13,14 @@ import ( ) var ( - s1 SubscribeFunc[string] = func(data string) { - println("s1") - } - - s2 SubscribeFunc[string] = func(data string) { - println("s2") - } + _ Publisher[int] = &Event[int]{} + _ Subscriber[int] = &Event[int]{} ) +func s1(data string) { println("s1") } + +func s2(data string) { println("s2") } + func TestPublisher_Publish(t *testing.T) { a := assert.New(t, false) e := New[string]() @@ -35,8 +34,8 @@ func TestPublisher_Publish(t *testing.T) { buf1.WriteString(data) } - c1, err := e.Subscribe(sub1) - a.NotError(err).NotNil(c1) + c1 := e.Subscribe(sub1) + a.NotNil(c1) e.Publish(true, "p1") time.Sleep(time.Microsecond * 500) a.Equal(buf1.String(), "p1") @@ -60,6 +59,9 @@ func TestPublisher_Publish(t *testing.T) { time.Sleep(time.Microsecond * 500) a.Empty(buf1.String()) a.Equal(buf2.String(), "p3") + + e.Reset() + a.Zero(e.len()) } func TestPublisher_Destroy(t *testing.T) { @@ -67,14 +69,12 @@ func TestPublisher_Destroy(t *testing.T) { e := New[string]() a.NotNil(e) - ee, ok := e.(*(event[string])) - a.True(ok).NotNil(ee).Zero(ee.len()) + a.Zero(e.len()) e = New[string]() a.NotNil(e) e.Subscribe(s1) - ee, ok = e.(*(event[string])) - a.True(ok).NotNil(ee).Equal(ee.len(), 1) + a.Equal(e.len(), 1) } func TestSubscriber_Attach_Detach(t *testing.T) { @@ -82,24 +82,20 @@ func TestSubscriber_Attach_Detach(t *testing.T) { e := New[string]() a.NotNil(e) - c1, err := e.Subscribe(s1) - a.NotError(err) - c2, err := e.Subscribe(s2) - a.NotError(err) - ee, ok := e.(*(event[string])) - a.True(ok).NotNil(ee) + c1 := e.Subscribe(s1) + c2 := e.Subscribe(s2) - a.Equal(ee.len(), 2) + a.Equal(e.len(), 2) c1() - a.Equal(ee.len(), 1) + a.Equal(e.len(), 1) c2() - a.Equal(ee.len(), 0) + a.Equal(e.len(), 0) } -func (e *event[T]) len() (c int) { - e.funcs.Range(func(key, value any) bool { +func (e *Event[T]) len() (c int) { + e.subscribers.Range(func(key, value any) bool { c++ return true })