aboutsummaryrefslogtreecommitdiffstats
path: root/event/dispatch.go
blob: e84da183e397b15c09ef9cb7dc1c2fa5038db306 (plain) (blame)
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
package event

import (
	"strings"
	"sync"
)

const Sep = "/"

type Dispatch struct {
	mu       sync.Mutex
	handlers []func(event string)
	trie     map[string]*Dispatch
}

func (d *Dispatch) Event(pattern string, handler func(event string)) {
	if pattern == "" {
		d.event(nil, handler)
		return
	}
	d.event(strings.Split(pattern, Sep), handler)
}

func (d *Dispatch) Happen(event string) {
	if event == "" {
		d.happen(nil)
		return
	}
	d.happen(strings.Split(event, Sep))
}

func (d *Dispatch) event(pattern []string, handler func(event string)) {
	d.mu.Lock()
	defer d.mu.Unlock()

	if len(pattern) == 0 {
		d.handlers = append(d.handlers, handler)
		return
	}

	if d.trie == nil {
		d.trie = make(map[string]*Dispatch)
	}
	if d.trie[pattern[0]] == nil {
		d.trie[pattern[0]] = &Dispatch{}
	}
	d.trie[pattern[0]].event(pattern[1:], handler)
}

func (d *Dispatch) happen(event []string) {
	d.mu.Lock()
	handlers := d.handlers
	d.mu.Unlock()

	for _, handler := range handlers {
		handler(strings.Join(event, Sep))
	}

	if len(event) == 0 {
		return
	}

	d.mu.Lock()
	next := d.trie[event[0]]
	d.mu.Unlock()

	if next != nil {
		next.happen(event[1:])
	}
}