Skip to content

Commit

Permalink
Change InitSingleton() to ResetSingleton() and create and store a glo…
Browse files Browse the repository at this point in the history
…bal EventBus object in init().
  • Loading branch information
werbenhu committed Sep 9, 2023
1 parent 310d672 commit 2d9a704
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 34 deletions.
14 changes: 10 additions & 4 deletions README-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,18 +73,24 @@ func main() {

### 使用全局的EventBus单例对象

为了更方便的使用EventBus, 这里有一个全局的EventBus单例对象,使用`eventbus.InitSingleton() `初始化这个单例对象,这个对象内部的channel是无缓冲的,直接使用`eventbus.Subscribe()`,`eventbus.Publish()`,`eventbus.Unsubscribe()`,将会调用该单例对象对应的方法。
为了更方便的使用EventBus, 这里有一个全局的EventBus单例对象,这个单例内部的channel是无缓冲的,直接使用`eventbus.Subscribe()`,`eventbus.Publish()`,`eventbus.Unsubscribe()`,将会调用该单例对象对应的方法。

```go
package main

import (
"fmt"
"time"

"github.com/werbenhu/eventbus"
)

func handler(topic string, payload int) {
fmt.Printf("topic:%s, payload:%d\n", topic, payload)
}

func main() {

// 初始化单例对象
eventbus.InitSingleton()

// eventbus.Subscribe() 将调用全局单例singleton.Subscribe()方法
eventbus.Subscribe("testtopic", handler)

Expand Down
14 changes: 10 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,18 +79,24 @@ func main() {
```

### Using the global singleton object of EventBus
To make it more convenient to use EventBus, there is a global singleton object for EventBus. You can initialize this singleton object by calling `eventbus.InitSingleton()`. The internal channel of this object is unbuffered, and you can directly use `eventbus.Subscribe()`, `eventbus.Publish()`, and `eventbus.Unsubscribe()` to call the corresponding methods of the singleton object.
To make it more convenient to use EventBus, there is a global singleton object for EventBus. The internal channel of this singleton is unbuffered, and you can directly use `eventbus.Subscribe()`, `eventbus.Publish()`, and `eventbus.Unsubscribe()` to call the corresponding methods of the singleton object.

```go
package main

import (
"fmt"
"time"

"github.com/werbenhu/eventbus"
)

func handler(topic string, payload int) {
fmt.Printf("topic:%s, payload:%d\n", topic, payload)
}

func main() {

// Initialize the singleton object
eventbus.InitSingleton()

// eventbus.Subscribe() will call the global singleton's Subscribe() method
eventbus.Subscribe("testtopic", handler)

Expand Down
20 changes: 13 additions & 7 deletions singleton.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,17 @@ var (
singleton *EventBus
)

// InitSingleton initializes the singleton instance of EventBus, which will be created only when necessary.
func InitSingleton() {
if singleton == nil {
func init() {
ResetSingleton()
}

// If singleton is nil, we create a new instance of EventBus using the New()
// function and assign it to the singleton variable.
singleton = New()
// ResetSingleton resets the singleton object. If the singleton object is not nil,
// it first closes the old singleton, and then creates a new singleton instance.
func ResetSingleton() {
if singleton != nil {
singleton.Close()
}
singleton = New()
}

// Unsubscribe removes handler defined for a topic.
Expand Down Expand Up @@ -42,5 +45,8 @@ func PublishSync(topic string, payload any) error {

// Close closes the singleton instance of EventBus.
func Close() {
singleton.Close()
if singleton != nil {
singleton.Close()
singleton = nil
}
}
61 changes: 42 additions & 19 deletions singleton_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,8 @@ import (
"github.com/stretchr/testify/assert"
)

func recreateSingleton() {
singleton = nil
InitSingleton()
}

func Test_InitSingleton(t *testing.T) {
recreateSingleton()
assert.NotNil(t, singleton)
}

func Test_SingletonSubscribe(t *testing.T) {
recreateSingleton()
ResetSingleton()
err := Subscribe("testtopic", busHandlerOne)
assert.Nil(t, err)
assert.NotNil(t, singleton)
Expand All @@ -37,14 +27,14 @@ func Test_SingletonSubscribe(t *testing.T) {
})

assert.Equal(t, ErrHandlerFirstParam, err)
Close()
singleton.Close()
err = Unsubscribe("testtopic", busHandlerTwo)
assert.Equal(t, ErrChannelClosed, err)
Close()
}

func Test_SingletonUnsubscribe(t *testing.T) {
recreateSingleton()

ResetSingleton()
err := Unsubscribe("testtopic", busHandlerOne)
assert.Equal(t, ErrNoSubscriber, err)
assert.NotNil(t, singleton)
Expand All @@ -54,15 +44,15 @@ func Test_SingletonUnsubscribe(t *testing.T) {

err = Unsubscribe("testtopic", busHandlerOne)
assert.Nil(t, err)
Close()
singleton.Close()

err = Unsubscribe("testtopic", busHandlerTwo)
assert.Equal(t, ErrChannelClosed, err)
Close()
}

func Test_SingletonPublish(t *testing.T) {
recreateSingleton()

ResetSingleton()
err := Publish("testtopic", 1)
assert.Nil(t, err)
assert.NotNil(t, singleton)
Expand All @@ -87,8 +77,7 @@ func Test_SingletonPublish(t *testing.T) {
}

func Test_SingletonPublishSync(t *testing.T) {
recreateSingleton()

ResetSingleton()
err := Publish("testtopic", 1)
assert.Nil(t, err)
assert.NotNil(t, singleton)
Expand All @@ -111,3 +100,37 @@ func Test_SingletonPublishSync(t *testing.T) {
wg.Wait()
Close()
}

func BenchmarkSingletonPublish(b *testing.B) {
ResetSingleton()
Subscribe("testtopic", busHandlerOne)

b.ResetTimer()
var wg sync.WaitGroup
wg.Add(1)
go func() {
for i := 0; i < b.N; i++ {
Publish("testtopic", i)
}
wg.Done()
}()
wg.Wait()
Close()
}

func BenchmarkSingletonPublishSync(b *testing.B) {
ResetSingleton()
Subscribe("testtopic", busHandlerOne)

b.ResetTimer()
var wg sync.WaitGroup
wg.Add(1)
go func() {
for i := 0; i < b.N; i++ {
PublishSync("testtopic", i)
}
wg.Done()
}()
wg.Wait()
Close()
}

0 comments on commit 2d9a704

Please sign in to comment.