| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 |
- package hub
-
- import "time"
-
- const hubGCEvery = time.Minute
-
- type connectionHub struct {
- sockets map[connectionID]*connection
-
- brokenSocketsChan chan connectionID
- connectionRequestsChan chan *connectionHubRequest
- returnConnectionsChan chan *connection
- }
-
- func (h *connectionHub) run() {
- gcTicker := time.NewTicker(hubGCEvery)
- defer gcTicker.Stop()
-
- for {
- select {
- case <-gcTicker.C:
- h.runGC()
- case id := <-h.brokenSocketsChan:
- h.runBrokenConnection(id)
- case request := <-h.connectionRequestsChan:
- h.runConnectionRequest(request)
- case conn := <-h.returnConnectionsChan:
- h.runReturnConnection(conn)
- }
- }
- }
-
- func (h *connectionHub) runBrokenConnection(id connectionID) {
- delete(h.sockets, id)
- }
-
- func (h *connectionHub) runGC() {
- for key, conn := range h.sockets {
- closing, pending := conn.Stats()
- switch {
- case closing:
- delete(h.sockets, key)
- case pending == 0:
- conn.Close()
- delete(h.sockets, key)
- return
- }
-
- }
- }
-
- func (h *connectionHub) runConnectionRequest(req *connectionHubRequest) {
- for key, conn := range h.sockets {
- closing, _ := conn.Stats()
- delete(h.sockets, key)
-
- if !closing {
- req.responseChan <- conn
- return
- }
- }
-
- newConn, err := newConnection(h, req.req)
- if err != nil {
- close(req.responseChan)
- return
- }
-
- req.responseChan <- newConn
- }
-
- func (h *connectionHub) runReturnConnection(conn *connection) {
- h.sockets[conn.id] = conn
- }
-
- func newConnectionHub() *connectionHub {
- return &connectionHub{
- sockets: map[connectionID]*connection{},
-
- brokenSocketsChan: make(chan connectionID, 1),
- connectionRequestsChan: make(chan *connectionHubRequest),
- returnConnectionsChan: make(chan *connection, 1),
- }
- }
|