github.com/brownsys/tracing-framework-go@v0.0.0-20161210174012-0542a62412fe/other/internal/gls/gls_goid.go (about)

     1  // +build goid
     2  
     3  package gls
     4  
     5  import (
     6  	"runtime"
     7  	"sync"
     8  )
     9  
    10  type bucket struct {
    11  	locals map[int64]*local
    12  	sync.RWMutex
    13  }
    14  
    15  type local struct {
    16  	m map[interface{}]interface{}
    17  	sync.RWMutex
    18  }
    19  
    20  var buckets = make([]bucket, 8*runtime.NumCPU())
    21  
    22  func init() {
    23  	for i := range buckets {
    24  		buckets[i].locals = make(map[int64]*local)
    25  	}
    26  }
    27  
    28  func getLocal() *local {
    29  	goid := runtime.Goid()
    30  	bkt := &buckets[int(goid%int64(len(buckets)))]
    31  	bkt.RLock()
    32  	l, ok := bkt.locals[goid]
    33  	bkt.RUnlock()
    34  	if !ok {
    35  		panic("gls: no goroutine-local storage; goroutine was not spawned with Go")
    36  	}
    37  	return l
    38  }
    39  
    40  func _go(f func()) {
    41  	go base(f)
    42  }
    43  
    44  func base(f func()) {
    45  	goid := runtime.Goid()
    46  	bkt := &buckets[int(goid%int64(len(buckets)))]
    47  
    48  	l := &local{m: make(map[interface{}]interface{})}
    49  	bkt.Lock()
    50  	bkt.locals[goid] = l
    51  	bkt.Unlock()
    52  
    53  	defer func() {
    54  		bkt.Lock()
    55  		delete(bkt.locals, goid)
    56  		bkt.Unlock()
    57  	}()
    58  
    59  	f()
    60  }
    61  
    62  func put(k, v interface{}) {
    63  	l := getLocal()
    64  	l.Lock()
    65  	// defer in case k is an invalid
    66  	// map key and the next line panics
    67  	defer l.Unlock()
    68  	l.m[k] = v
    69  }
    70  
    71  func get(k interface{}) (interface{}, bool) {
    72  	l := getLocal()
    73  	l.RLock()
    74  	// defer in case k is an invalid
    75  	// map key and the next line panics
    76  	defer l.RUnlock()
    77  	v, ok := l.m[k]
    78  	return v, ok
    79  }
    80  
    81  func del(k interface{}) {
    82  	l := getLocal()
    83  	l.Lock()
    84  	// defer in case k is an invalid
    85  	// map key and the next line panics
    86  	defer l.Unlock()
    87  	delete(l.m, k)
    88  }