Skip to content

Instantly share code, notes, and snippets.

@momchil-velikov
Created May 18, 2016 11:58
Show Gist options
  • Save momchil-velikov/c2a7e2d508e8245d3e96f820527e296d to your computer and use it in GitHub Desktop.
Save momchil-velikov/c2a7e2d508e8245d3e96f820527e296d to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"sync"
"time"
)
type BlockingMap struct {
Map map[string]int
Pending map[string][]*sync.Cond
Lock *sync.Mutex
}
func New() *BlockingMap {
return &BlockingMap{Map: map[string]int{}, Pending: map[string][]*sync.Cond{}, Lock: new(sync.Mutex)}
}
func (m *BlockingMap) Put(key string, val int) {
m.Lock.Lock()
defer func() { m.Lock.Unlock() }()
m.Map[key] = val
for _, cv := range m.Pending[key] {
cv.Signal()
}
m.Pending[key] = nil
}
func (m *BlockingMap) Get(key string, cv *sync.Cond) int {
m.Lock.Lock()
defer func() { m.Lock.Unlock() }()
if val, ok := m.Map[key]; ok {
return val
}
m.Pending[key] = append(m.Pending[key], cv)
cv.L = m.Lock
for {
val, ok := m.Map[key]
if ok {
return val
}
cv.Wait()
}
}
func main() {
m := New()
go func() {
time.Sleep(1 * time.Second)
m.Put("x", 1)
time.Sleep(1 * time.Second)
m.Put("y", 2)
time.Sleep(1 * time.Second)
m.Put("z", 3)
}()
cv := sync.NewCond(nil)
i := m.Get("x", cv)
fmt.Println(i)
i = m.Get("y", cv)
fmt.Println(i)
i = m.Get("y", cv)
fmt.Println(i)
i = m.Get("z", cv)
fmt.Println(i)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment