@@ -31,10 +31,26 @@ func (s *Stream) Register(c *Client) {
31
31
s .addClient (c )
32
32
}
33
33
34
+ // Remove will remove a client from this stream, but not shut the client down.
35
+ func (s * Stream ) Remove (c * Client ) {
36
+ s .listLock .Lock ()
37
+ defer s .listLock .Unlock ()
38
+
39
+ for element := s .clients .Front (); element != nil ; element = element .Next () {
40
+ if regCli := element .Value .(* registeredClient ); regCli .c == c {
41
+ // client found
42
+ s .clients .Remove (element )
43
+ return
44
+ }
45
+ }
46
+ }
47
+
34
48
// Broadcast sends the event to all clients registered on this stream.
35
49
func (s * Stream ) Broadcast (e * Event ) {
50
+ s .listLock .RLock ()
51
+ defer s .listLock .RUnlock ()
36
52
37
- for element := s .clients .Front (); element != nil ; element .Next () {
53
+ for element := s .clients .Front (); element != nil ; element = element .Next () {
38
54
cli := element .Value .(* registeredClient )
39
55
cli .c .Send (e )
40
56
}
@@ -44,7 +60,6 @@ func (s *Stream) Broadcast(e *Event) {
44
60
// to this topic. Subscribe will also Register an unregistered
45
61
// client.
46
62
func (s * Stream ) Subscribe (topic string , c * Client ) {
47
-
48
63
// see if the client is registered
49
64
cli := s .getClient (c )
50
65
@@ -58,6 +73,7 @@ func (s *Stream) Subscribe(topic string, c *Client) {
58
73
59
74
// Unsubscribe removes clients from the topic, but not from broadcasts.
60
75
func (s * Stream ) Unsubscribe (topic string , c * Client ) {
76
+
61
77
cli := s .getClient (c )
62
78
if cli == nil {
63
79
return
@@ -67,7 +83,10 @@ func (s *Stream) Unsubscribe(topic string, c *Client) {
67
83
68
84
// Publish sends the event to clients that have subscribed to the given topic.
69
85
func (s * Stream ) Publish (topic string , e * Event ) {
70
- for element := s .clients .Front (); element != nil ; element .Next () {
86
+ s .listLock .RLock ()
87
+ defer s .listLock .Unlock ()
88
+
89
+ for element := s .clients .Front (); element != nil ; element = element .Next () {
71
90
cli := element .Value .(* registeredClient )
72
91
if cli .topics [topic ] {
73
92
cli .c .Send (e )
@@ -77,7 +96,10 @@ func (s *Stream) Publish(topic string, e *Event) {
77
96
78
97
// Shutdown terminates all clients connected to the stream and removes them
79
98
func (s * Stream ) Shutdown () {
80
- for element := s .clients .Front (); element != nil ; element .Next () {
99
+ s .listLock .Lock ()
100
+ defer s .listLock .Unlock ()
101
+
102
+ for element := s .clients .Front (); element != nil ; element = element .Next () {
81
103
cli := element .Value .(* registeredClient )
82
104
cli .c .Shutdown ()
83
105
s .clients .Remove (element )
@@ -110,6 +132,7 @@ func (s *Stream) ServeHTTP(w http.ResponseWriter, r *http.Request) {
110
132
// wait for the client to exit or be shutdown
111
133
s .Register (c )
112
134
c .Wait ()
135
+ s .Remove (c )
113
136
}
114
137
115
138
// TopicHandler returns an HTTP handler that will register a client for broadcasts
@@ -140,6 +163,7 @@ func (s *Stream) TopicHandler(topics []string) http.HandlerFunc {
140
163
141
164
// wait for the client to exit or be shutdown
142
165
c .Wait ()
166
+ s .Remove (c )
143
167
}
144
168
}
145
169
@@ -155,18 +179,17 @@ func checkRequest(r *http.Request) bool {
155
179
}
156
180
157
181
func (s * Stream ) getClient (c * Client ) * registeredClient {
158
- if s .clients .Len () > 0 {
159
- // ensure client is not already registered
160
- s .listLock .RLock ()
182
+ s .listLock .RLock ()
183
+ defer s .listLock .RUnlock ()
161
184
162
- listItem := s .clients .Front ()
163
- if regCli := listItem .Value .(* registeredClient ); regCli .c == c {
185
+ for element := s .clients .Front (); element != nil ; element = element . Next () {
186
+ if regCli := element .Value .(* registeredClient ); regCli .c == c {
164
187
// client found
165
- s .listLock .RUnlock ()
166
188
return regCli
167
189
}
168
190
}
169
191
192
+ // not found
170
193
return nil
171
194
}
172
195
0 commit comments