Skip to content

Commit 5b2fa8d

Browse files
committed
init
1 parent 1a3eaf6 commit 5b2fa8d

File tree

6 files changed

+163
-15
lines changed

6 files changed

+163
-15
lines changed

.gitignore

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1 @@
1-
# Binaries for programs and plugins
2-
*.exe
3-
*.exe~
4-
*.dll
5-
*.so
6-
*.dylib
7-
8-
# Test binary, built with `go test -c`
9-
*.test
10-
11-
# Output of the go coverage tool, specifically when used with LiteIDE
12-
*.out
13-
14-
# Dependency directories (remove the comment below to include it)
15-
# vendor/
1+
.idea/*

README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,31 @@
11
# gls
22
goroutine local storage
3+
4+
# demo
5+
```
6+
package main
7+
8+
import (
9+
"fmt"
10+
"github.com/go-basic/gls"
11+
"sync"
12+
)
13+
14+
func main() {
15+
var wg sync.WaitGroup
16+
for i := 0; i < 5; i++ {
17+
wg.Add(1)
18+
go func(idx int) {
19+
defer wg.Done()
20+
defer gls.Clean()
21+
22+
defer func() {
23+
fmt.Printf("%d: number = %d\n", idx, gls.Get("number"))
24+
}()
25+
gls.Set("number", idx+100)
26+
}(i)
27+
}
28+
wg.Wait()
29+
}
30+
31+
```

examples/main.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"github.com/go-basic/gls"
6+
"sync"
7+
)
8+
9+
func main() {
10+
var wg sync.WaitGroup
11+
for i := 0; i < 5; i++ {
12+
wg.Add(1)
13+
go func(idx int) {
14+
defer wg.Done()
15+
defer gls.Clean()
16+
17+
defer func() {
18+
fmt.Printf("%d: number = %d\n", idx, gls.Get("number"))
19+
}()
20+
gls.Set("number", idx+100)
21+
}(i)
22+
}
23+
wg.Wait()
24+
}

gls.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package gls
2+
3+
import (
4+
"fmt"
5+
"runtime"
6+
"strconv"
7+
"strings"
8+
"sync"
9+
)
10+
11+
var gls struct {
12+
m map[int64]map[interface{}]interface{}
13+
sync.RWMutex
14+
}
15+
16+
func init() {
17+
gls.m = make(map[int64]map[interface{}]interface{})
18+
}
19+
20+
func GetGoId() int64 {
21+
var (
22+
buf [64]byte
23+
n = runtime.Stack(buf[:], false)
24+
stk = strings.TrimPrefix(string(buf[:n]), "goroutine ")
25+
)
26+
idField := strings.Fields(stk)[0]
27+
id, err := strconv.Atoi(idField)
28+
if err != nil {
29+
panic(fmt.Errorf("can not get goroutine id: %v", err))
30+
}
31+
return int64(id)
32+
}
33+
34+
func Get(key interface{}) interface{} {
35+
gls.RLock()
36+
defer gls.RUnlock()
37+
goId := GetGoId()
38+
return gls.m[goId][key]
39+
}
40+
41+
func Set(key interface{}, v interface{}) {
42+
gls.Lock()
43+
defer gls.Unlock()
44+
goId := GetGoId()
45+
if _, ok := gls.m[goId][key]; !ok {
46+
gls.m[goId] = make(map[interface{}]interface{})
47+
}
48+
gls.m[goId][key] = v
49+
}
50+
51+
func Clean() {
52+
gls.Lock()
53+
defer gls.Unlock()
54+
delete(gls.m, GetGoId())
55+
}

gls_test.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package gls
2+
3+
import (
4+
"fmt"
5+
"strconv"
6+
"testing"
7+
)
8+
9+
var key = "test"
10+
11+
func GO(fn func()) {
12+
go fn()
13+
}
14+
15+
func TestGls(t *testing.T) {
16+
GO(func() {
17+
defer Clean()
18+
Set(key, "aaa")
19+
testPrint()
20+
})
21+
GO(func() {
22+
defer Clean()
23+
Set(key, "bbb")
24+
testPrint()
25+
})
26+
GO(func() {
27+
defer Clean()
28+
Set(key, "ccc")
29+
testPrint()
30+
})
31+
}
32+
33+
34+
func BenchmarkGls(b *testing.B) {
35+
for i := 0; i < b.N; i++ {
36+
GO(func() {
37+
defer Clean()
38+
Set(key, "ccc"+strconv.FormatInt(GetGoId(), 10))
39+
testGet()
40+
})
41+
}
42+
}
43+
44+
func testPrint() {
45+
fmt.Println(Get(key), GetGoId())
46+
}
47+
48+
func testGet() {
49+
Get(key)
50+
}
51+

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module github.com/go-basic/gls
2+
3+
go 1.15

0 commit comments

Comments
 (0)