-
Notifications
You must be signed in to change notification settings - Fork 22
/
room.go
104 lines (90 loc) · 2.48 KB
/
room.go
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/*
Copyright 2013 Niklas Voss
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package golem
const (
roomSendChannelSize = 32
)
// Rooms are groups of connections. A room provides methods to communicate with all
// members of the group simultaneously.
type Room struct {
// Map of member connections
members map[*Connection]bool
// Stop channel
stop chan bool
// Join request
join chan *Connection
// Leave request
leave chan *Connection
// Broadcast to room members
send chan *message
}
// Creates and initialised a room and returns pointer to it.
func NewRoom() *Room {
r := Room{
members: make(map[*Connection]bool),
stop: make(chan bool),
join: make(chan *Connection),
leave: make(chan *Connection),
send: make(chan *message, roomSendChannelSize),
}
// Run the message loop
go r.run()
// Return pointer
return &r
}
// Starts the message loop of this room, should only be run once and in a different routine.
func (r *Room) run() {
for {
select {
// Join
case conn := <-r.join:
r.members[conn] = true
// Leave
case conn := <-r.leave:
if _, ok := r.members[conn]; ok { // If member exists, delete it
delete(r.members, conn)
}
// Send
case message := <-r.send:
for conn := range r.members { // For every connection try to send
select {
case conn.send <- message:
default: // If sending failed, delete member
delete(r.members, conn)
}
}
// Stop
case <-r.stop:
return
}
}
}
// Stops and shutsdown the room. After calling Stop the room can be safely deleted.
func (r *Room) Stop() {
r.stop <- true
}
// Join adds the provided connection to the room.
func (r *Room) Join(conn *Connection) {
r.join <- conn
}
// Leave removes the connection from the room, if it previously was member of the room.
func (r *Room) Leave(conn *Connection) {
r.leave <- conn
}
// Emits message event to all members of the room.
func (r *Room) Emit(event string, data interface{}) {
r.send <- &message{
event: event,
data: data,
}
}