@@ -5,13 +5,13 @@ import (
5
5
"time"
6
6
7
7
"v2ray.com/core/common"
8
+ "v2ray.com/core/common/signal/done"
8
9
"v2ray.com/core/common/task"
9
10
)
10
11
11
12
type Subscriber struct {
12
- name string
13
- buffer chan interface {}
14
- removed chan struct {}
13
+ buffer chan interface {}
14
+ done * done.Instance
15
15
}
16
16
17
17
func (s * Subscriber ) push (msg interface {}) {
@@ -25,62 +25,66 @@ func (s *Subscriber) Wait() <-chan interface{} {
25
25
return s .buffer
26
26
}
27
27
28
- func (s * Subscriber ) Close () {
29
- close ( s . removed )
28
+ func (s * Subscriber ) Close () error {
29
+ return s . done . Close ( )
30
30
}
31
31
32
32
func (s * Subscriber ) IsClosed () bool {
33
- select {
34
- case <- s .removed :
35
- return true
36
- default :
37
- return false
38
- }
33
+ return s .done .Done ()
39
34
}
40
35
41
36
type Service struct {
42
37
sync.RWMutex
43
- subs []* Subscriber
38
+ subs map [ string ] []* Subscriber
44
39
ctask * task.Periodic
45
40
}
46
41
47
42
func NewService () * Service {
48
- s := & Service {}
43
+ s := & Service {
44
+ subs : make (map [string ][]* Subscriber ),
45
+ }
49
46
s .ctask = & task.Periodic {
50
- Execute : s .cleanup ,
47
+ Execute : s .Cleanup ,
51
48
Interval : time .Second * 30 ,
52
49
}
53
50
common .Must (s .ctask .Start ())
54
51
return s
55
52
}
56
53
57
- func (s * Service ) cleanup () error {
54
+ // Cleanup cleans up internal caches of subscribers.
55
+ // Visible for testing only.
56
+ func (s * Service ) Cleanup () error {
58
57
s .Lock ()
59
58
defer s .Unlock ()
60
59
61
- if len (s .subs ) < 16 {
62
- return nil
63
- }
64
-
65
- newSub := make ([]* Subscriber , 0 , len (s .subs ))
66
- for _ , sub := range s .subs {
67
- if ! sub .IsClosed () {
68
- newSub = append (newSub , sub )
60
+ for name , subs := range s .subs {
61
+ newSub := make ([]* Subscriber , 0 , len (s .subs ))
62
+ for _ , sub := range subs {
63
+ if ! sub .IsClosed () {
64
+ newSub = append (newSub , sub )
65
+ }
66
+ }
67
+ if len (newSub ) == 0 {
68
+ delete (s .subs , name )
69
+ } else {
70
+ s .subs [name ] = newSub
69
71
}
70
72
}
71
73
72
- s .subs = newSub
74
+ if len (s .subs ) == 0 {
75
+ s .subs = make (map [string ][]* Subscriber )
76
+ }
73
77
return nil
74
78
}
75
79
76
80
func (s * Service ) Subscribe (name string ) * Subscriber {
77
81
sub := & Subscriber {
78
- name : name ,
79
- buffer : make (chan interface {}, 16 ),
80
- removed : make (chan struct {}),
82
+ buffer : make (chan interface {}, 16 ),
83
+ done : done .New (),
81
84
}
82
85
s .Lock ()
83
- s .subs = append (s .subs , sub )
86
+ subs := append (s .subs [name ], sub )
87
+ s .subs [name ] = subs
84
88
s .Unlock ()
85
89
return sub
86
90
}
@@ -89,8 +93,8 @@ func (s *Service) Publish(name string, message interface{}) {
89
93
s .RLock ()
90
94
defer s .RUnlock ()
91
95
92
- for _ , sub := range s .subs {
93
- if sub . name == name && ! sub .IsClosed () {
96
+ for _ , sub := range s .subs [ name ] {
97
+ if ! sub .IsClosed () {
94
98
sub .push (message )
95
99
}
96
100
}
0 commit comments