Skip to content

Commit

Permalink
refactor: 删除 Eventer 接口
Browse files Browse the repository at this point in the history
  • Loading branch information
caixw committed Apr 18, 2024
1 parent 9991d89 commit 10163e3
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 60 deletions.
78 changes: 42 additions & 36 deletions events.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
})
}
44 changes: 20 additions & 24 deletions events_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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]()
Expand All @@ -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")
Expand All @@ -60,46 +59,43 @@ 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) {
a := assert.New(t, false)

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) {
a := assert.New(t, false)
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
})
Expand Down

0 comments on commit 10163e3

Please sign in to comment.