Skip to content

Instantly share code, notes, and snippets.

@aybabtme
Created August 27, 2015 19:29
Show Gist options
  • Save aybabtme/8d1c75dcb51216644ea8 to your computer and use it in GitHub Desktop.
Save aybabtme/8d1c75dcb51216644ea8 to your computer and use it in GitHub Desktop.
package p2p
import (
"bytes"
"fmt"
"os"
"os/signal"
"runtime"
"sync"
"sync/atomic"
"syscall"
)
var (
mu sync.Mutex
blocked = make(map[uint64]map[string]struct{})
locked = make(map[uint64]map[string]struct{})
ids uint64
)
func init() {
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGUSR1)
go func() {
buf := bytes.NewBuffer(nil)
for range c {
mu.Lock()
fmt.Fprintln(buf, "blocked:")
for id, blocks := range blocked {
fmt.Fprintf(buf, "\tmutex %d\n", id)
for block := range blocks {
fmt.Fprintln(buf, "\t\t", block)
}
}
fmt.Fprintln(buf, "locked:")
for id, locks := range locked {
fmt.Fprintf(buf, "\tmutex %d\n", id)
for lock := range locks {
fmt.Fprintln(buf, "\t\t", lock)
}
}
mu.Unlock()
os.Stderr.Write(buf.Bytes())
buf.Reset()
}
}()
}
type syncMutex struct {
sync.Mutex
id uint64
once sync.Once
}
func (s *syncMutex) Lock() {
s.once.Do(func() {
s.id = atomic.AddUint64(&ids, 1)
})
_, file, line, _ := runtime.Caller(1)
key := fmt.Sprintf("%s:%d", file, line)
mu.Lock()
{
lock, ok := blocked[s.id]
if !ok {
lock = make(map[string]struct{})
}
lock[key] = struct{}{}
blocked[s.id] = lock
}
mu.Unlock()
s.Mutex.Lock()
mu.Lock()
delete(blocked[s.id], key)
if len(blocked[s.id]) == 0 {
delete(blocked, s.id)
}
{
lock, ok := locked[s.id]
if !ok {
lock = make(map[string]struct{})
}
lock[key] = struct{}{}
locked[s.id] = lock
}
mu.Unlock()
}
func (s *syncMutex) Unlock() {
s.once.Do(func() {
s.id = atomic.AddUint64(&ids, 1)
})
_, file, line, _ := runtime.Caller(1)
key := fmt.Sprintf("%s:%d", file, line)
s.Mutex.Unlock()
mu.Lock()
delete(locked[s.id], key)
if len(locked[s.id]) == 0 {
delete(locked, s.id)
}
mu.Unlock()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment