diff options
author | raylu <raylu@mixpanel.com> | 2011-08-08 02:47:10 -0700 |
---|---|---|
committer | raylu <raylu@mixpanel.com> | 2011-08-08 02:47:10 -0700 |
commit | 578e1a2e6c83aa4cfc8686b25f899db863f09f10 (patch) | |
tree | c6211618655a50381a36bb87ccf67dd5177fab58 | |
parent | 0164e2515ae5ff6cedf37c4ae8344eae4d1b9b94 (diff) | |
download | audioaxis-578e1a2e6c83aa4cfc8686b25f899db863f09f10.tar.xz |
redo update code
-rw-r--r-- | main.go | 30 | ||||
-rw-r--r-- | updates.go | 66 |
2 files changed, 68 insertions, 28 deletions
@@ -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("[]")) } @@ -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 } |