From 578e1a2e6c83aa4cfc8686b25f899db863f09f10 Mon Sep 17 00:00:00 2001 From: raylu Date: Mon, 8 Aug 2011 02:47:10 -0700 Subject: redo update code --- main.go | 30 +++++++++++++--------------- updates.go | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 68 insertions(+), 28 deletions(-) diff --git a/main.go b/main.go index 21af0a8..de39411 100644 --- a/main.go +++ b/main.go @@ -262,25 +262,21 @@ func poll(w http.ResponseWriter, r *http.Request) { http.Error(w, err.String(), http.StatusInternalServerError) return } - var update *Update - for i := 0; i < 30; i++ { - update = getUpdates(q.Get("pid"), timestamp) - if update != nil { - w.Write([]byte("[")) - for update != nil { - output, err := json.MarshalForHTML(update) - if err == nil { - w.Write(output) - } - update = update.Next - if update != nil { - w.Write([]byte(",")) - } + update := getUpdates(q.Get("pid"), timestamp) + if update != nil { + w.Write([]byte("[")) + for update != nil { + output, err := json.MarshalForHTML(update) + if err == nil { + w.Write(output) + } + update = update.Next + if update != nil { + w.Write([]byte(",")) } - w.Write([]byte("]")) - return } - time.Sleep(1e9) // 1 second + w.Write([]byte("]")) + return } w.Write([]byte("[]")) } 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 } -- cgit v1.2.3