Skip to content

Commit

Permalink
add tls
Browse files Browse the repository at this point in the history
  • Loading branch information
xhd2015 committed Apr 10, 2024
1 parent 60d0e31 commit 43df2f9
Show file tree
Hide file tree
Showing 5 changed files with 195 additions and 4 deletions.
4 changes: 2 additions & 2 deletions cmd/xgo/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package main
import "fmt"

const VERSION = "1.0.20"
const REVISION = "7ab84d83e8d847f0c2307a44866705581ba5cbbe+1"
const NUMBER = 172
const REVISION = "60d0e314753d95e7d630a307ef991ac7bc21807e+1"
const NUMBER = 173

func getRevision() string {
revSuffix := ""
Expand Down
4 changes: 2 additions & 2 deletions runtime/core/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (
)

const VERSION = "1.0.20"
const REVISION = "7ab84d83e8d847f0c2307a44866705581ba5cbbe+1"
const NUMBER = 172
const REVISION = "60d0e314753d95e7d630a307ef991ac7bc21807e+1"
const NUMBER = 173

// these fields will be filled by compiler
const XGO_VERSION = ""
Expand Down
50 changes: 50 additions & 0 deletions runtime/tls/hook.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package tls

import (
"fmt"
"os"
"unsafe"
)

func __xgo_link_on_gonewproc(f func(g uintptr)) {
fmt.Fprintln(os.Stderr, "WARNING: failed to link __xgo_link_on_gonewproc(requires xgo).")
}

func __xgo_link_getcurg() unsafe.Pointer {
fmt.Fprintln(os.Stderr, "WARNING: failed to link __xgo_link_getcurg(requires xgo).")
return nil
}

func __xgo_link_on_goexit(fn func()) {
fmt.Fprintln(os.Stderr, "WARNING: failed to link __xgo_link_on_goexit(requires xgo).")
}

func init() {
__xgo_link_on_goexit(func() {
// clear when exit
g := uintptr(__xgo_link_getcurg())
mut.Lock()
localKeys := keys
mut.Unlock()
for _, loc := range localKeys {
loc.store.Delete(g)
}
})
__xgo_link_on_gonewproc(func(newg uintptr) {
// inherit when new goroutine
g := uintptr(__xgo_link_getcurg())
mut.Lock()
localKeys := keys
mut.Unlock()
for _, loc := range localKeys {
if !loc.inherit {
continue
}
val, ok := loc.store.Load(g)
if !ok {
continue
}
loc.store.Store(newg, val)
}
})
}
85 changes: 85 additions & 0 deletions runtime/tls/tls.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package tls

import (
"sync"
)

var mut sync.Mutex
var keys []*tlsKey

type TLSKey interface {
Get() interface{}
GetOK() (interface{}, bool)
Set(v interface{})
}

type tlsKey struct {
name string // for debugging purepose
inherit bool
store sync.Map // <goroutine ptr> -> interface{}
}

var _ TLSKey = (*tlsKey)(nil)

func Declare(name string) TLSKey {
b := &TLSBuilder{
name: name,
}
return b.Declare()
}
func DeclareInherit(name string) TLSKey {
b := &TLSBuilder{
name: name,
inherit: true,
}
return b.Declare()
}

type TLSBuilder struct {
name string
inherit bool
}

func New() *TLSBuilder {
return &TLSBuilder{}
}

func (c *TLSBuilder) Name(name string) *TLSBuilder {
c.name = name
return c
}

func (c *TLSBuilder) Inherit() *TLSBuilder {
c.inherit = true
return c
}

func (c *TLSBuilder) Declare() TLSKey {
key := &tlsKey{
name: c.name,
inherit: c.inherit,
}
mut.Lock()
keys = append(keys, key)
mut.Unlock()
return key
}

func (c *tlsKey) Get() interface{} {
key := uintptr(__xgo_link_getcurg())
val, ok := c.store.Load(key)
if !ok {
return nil
}
return val
}

func (c *tlsKey) GetOK() (interface{}, bool) {
key := uintptr(__xgo_link_getcurg())
return c.store.Load(key)
}

func (c *tlsKey) Set(v interface{}) {
key := uintptr(__xgo_link_getcurg())
c.store.Store(key, v)
}
56 changes: 56 additions & 0 deletions runtime/tls/tls_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package tls_test

import (
"testing"

"github.com/xhd2015/xgo/runtime/tls"
)

var a = tls.Declare("a")
var b = tls.DeclareInherit("b")

func TestDeclareLocal(t *testing.T) {
a.Set(1)

var v1 interface{}
done := make(chan struct{})
go func() {
v1 = a.Get()
close(done)
}()
<-done

v2 := a.Get()

if v1 != nil {
t.Fatalf("expect sub goroutine get nil, actual: %v", v1)
}

if i := v2.(int); i != 1 {
t.Fatalf("expect current goroutine get %d, actual: %d", 1, i)
}
}

func TestInerhitLocal(t *testing.T) {
b.Set(1)

var v1 interface{}
done := make(chan struct{})
go func() {
v1 = b.Get()
close(done)
}()
<-done

v2 := b.Get()

if v1 == nil {
t.Fatalf("expect sub goroutine inerit b, actual: %v", v1)

Check warning on line 48 in runtime/tls/tls_test.go

View workflow job for this annotation

GitHub Actions / build

"inerit" should be "inherit".
}
if i := v1.(int); i != 1 {
t.Fatalf("expect sub goroutine get %d, actual: %d", 1, i)
}
if i := v2.(int); i != 1 {
t.Fatalf("expect current goroutine get %d, actual: %d", 1, i)
}
}

0 comments on commit 43df2f9

Please sign in to comment.