diff options
Diffstat (limited to 'updates.go')
-rw-r--r-- | updates.go | 66 |
1 files changed, 55 insertions, 11 deletions
@@ -2,6 +2,7 @@ package main import ( "time" + "sync" ) const ( @@ -16,12 +17,20 @@ type Update struct { Timestamp int64 Next *Update } +type Listener struct { + L chan bool + Next *Listener +} + var headUpdates map[int]*Update var tailUpdates map[int]*Update +var listeners map[int]*Listener +var updateLock sync.Mutex func init() { headUpdates = make(map[int]*Update) tailUpdates = make(map[int]*Update) + listeners = make(map[int]*Listener) } func addUpdate(pid int, action uint, song *Song) { @@ -29,13 +38,36 @@ func addUpdate(pid int, action uint, song *Song) { update.Song = song update.Action = action update.Timestamp = time.Nanoseconds() - pup, ok := tailUpdates[pid] - if ok { + + updateLock.Lock() + defer updateLock.Unlock() + + pup := tailUpdates[pid] + if pup != nil { pup.Next = update } else { headUpdates[pid] = update } tailUpdates[pid] = update + + listener := listeners[pid] + for listener != nil { + listener.L <- true + listener = listener.Next + } + listeners[pid] = nil +} + +// assumes locked +func checkUpdates(pid int, timestamp int64) *Update { + pup, _ := headUpdates[pid] + for pup != nil { + if pup.Timestamp > timestamp { + return pup + } + pup = pup.Next + } + return nil } func getUpdates(id string, timestamp int64) *Update { @@ -45,15 +77,27 @@ func getUpdates(id string, timestamp int64) *Update { if pid == -1 { return nil } - pup, ok := headUpdates[pid] - if !ok { - return nil + + updateLock.Lock() + pup := checkUpdates(pid, timestamp) + if pup != nil { + updateLock.Unlock() + return pup } - for pup != nil { - if pup.Timestamp > timestamp { - return pup - } - pup = pup.Next + + // didn't get updates + listener := new(Listener) + listener.L = make(chan bool) + lhead := listeners[pid] + if lhead != nil { + listener.Next = lhead } - return nil + listeners[pid] = listener + updateLock.Unlock() + <-listener.L + + updateLock.Lock() + pup = checkUpdates(pid, timestamp) + updateLock.Unlock() + return pup } |