summaryrefslogtreecommitdiffstats
path: root/updates.go
diff options
context:
space:
mode:
Diffstat (limited to 'updates.go')
-rw-r--r--updates.go66
1 files changed, 55 insertions, 11 deletions
diff --git a/updates.go b/updates.go
index 28480c4..78db802 100644
--- a/updates.go
+++ b/updates.go
@@ -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
}