2013-09-04 22:02:17 -04:00
|
|
|
/*
|
|
|
|
Copyright (C) 2013 Aaron Lindsay <aaron@aclindsay.com>
|
|
|
|
*/
|
|
|
|
|
2013-03-09 22:47:49 -05:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"asink"
|
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
type LongPollGroup struct {
|
|
|
|
channels []*chan *asink.Event
|
|
|
|
lock sync.Mutex
|
|
|
|
}
|
|
|
|
|
|
|
|
type PollingManager struct {
|
|
|
|
lock sync.RWMutex
|
2013-08-28 23:05:28 -04:00
|
|
|
groups map[int64]*LongPollGroup
|
2013-03-09 22:47:49 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
var pm *PollingManager
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
pm = new(PollingManager)
|
2013-08-28 23:05:28 -04:00
|
|
|
pm.groups = make(map[int64]*LongPollGroup)
|
2013-03-09 22:47:49 -05:00
|
|
|
}
|
|
|
|
|
2013-08-28 23:05:28 -04:00
|
|
|
func addPoller(uid int64, channel *chan *asink.Event) {
|
2013-03-09 22:47:49 -05:00
|
|
|
pm.lock.RLock()
|
|
|
|
|
|
|
|
group := pm.groups[uid]
|
|
|
|
if group != nil {
|
|
|
|
group.lock.Lock()
|
|
|
|
pm.lock.RUnlock()
|
|
|
|
group.channels = append(group.channels, channel)
|
|
|
|
group.lock.Unlock()
|
|
|
|
} else {
|
|
|
|
pm.lock.RUnlock()
|
|
|
|
pm.lock.Lock()
|
|
|
|
group = new(LongPollGroup)
|
|
|
|
group.channels = append(group.channels, channel)
|
|
|
|
pm.groups[uid] = group
|
|
|
|
pm.lock.Unlock()
|
|
|
|
}
|
|
|
|
|
|
|
|
//set timer to call function after one minute
|
2013-03-18 07:17:44 -04:00
|
|
|
timeout := time.Duration(1) * time.Minute
|
2013-03-09 22:47:49 -05:00
|
|
|
time.AfterFunc(timeout, func() {
|
|
|
|
group.lock.Lock()
|
|
|
|
for i, c := range group.channels {
|
|
|
|
if c == channel {
|
|
|
|
copy(group.channels[i:], group.channels[i+1:])
|
|
|
|
group.channels = group.channels[:len(group.channels)-1]
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
group.lock.Unlock()
|
|
|
|
close(*channel)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2013-08-28 23:05:28 -04:00
|
|
|
func broadcastToPollers(uid int64, event *asink.Event) {
|
2013-03-09 22:47:49 -05:00
|
|
|
//store off the long polling group we're trying to send to and remove
|
|
|
|
//it from PollingManager.groups
|
|
|
|
pm.lock.Lock()
|
|
|
|
group := pm.groups[uid]
|
|
|
|
pm.groups[uid] = nil
|
|
|
|
pm.lock.Unlock()
|
|
|
|
|
|
|
|
//send event down each of group's channels
|
|
|
|
if group != nil {
|
|
|
|
group.lock.Lock()
|
|
|
|
for _, c := range group.channels {
|
|
|
|
*c <- event
|
|
|
|
}
|
|
|
|
group.lock.Unlock()
|
|
|
|
}
|
|
|
|
}
|