gls

package
v0.0.0-...-f54e8e0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 7, 2024 License: MPL-2.0, BSD-3-Clause Imports: 0 Imported by: 0

README

gls

Fast goroutine local storage.

This is a reduced library, extracted from cosmos72/gls. See the original for the full version.

WARNING

There is extensive documentation and discussion on why implementing and using thread-local storage in Go - actually, goroutine-local storage - is a bad idea.

See for example the Go FAQ on goroutine id and context.Context, which is how you're encouraged to solve problems that would require a goroutine-local storage.

The main obstacle in adopting context.Context is that all of your functions must have a new first argument. So, if that horrifies you or is simply not feasible for your use case, feel free to ignore this warning and read on.

Just remember that, if some Go programmers frowns at your use of goroutine-local storage, there are good reasons.

Why?

To retrieve per-goroutine data that some function did not - or could not - pass through the call chain, down to where you need it.

Other goroutine-local libraries, as jtolds/gls and tylerb/gls explain the reasons and use cases for goroutine-local storage more in detail.

Status

Beta.

Lightly tested on 386, amd64, arm, arm64, mips, ppc64le with Go 1.10.1. Other architectures (mips64, mips64le, mipsle, ppc64, riscv64, s390x) supported in theory but not tested.

How it works

Go runtime has an internal, i.e. unexported, goroutine-local runtime.g struct. It is used for several purposes, including defer(), recover(), by the goroutine scheduler, and it even has an unexported goid field, i.e. a goroutine ID.

Several other goroutine-local libraries extract this goroutine ID with various tricks, most notably from runtime.Stack() textual output.

Instead, we use a tiny bit of assembler code to retrieve the address of the runtime.g struct and return it converted to an opaque uintptr.

We use it as the key in a global variable containing per-goroutine data.

This is also fast, probably orders of magnitude faster than most other solutions.

Why not the same goroutine ID?

To avoid fiddling with the internal layout of runtime.g struct, we only take its address.

Accessing the goid field would require knowing its offset within the struct, which is both tedious and error-prone to retrieve, since it's an unexported field of an unexported struct type.

Documentation

See the autogenerated API docs at http://godoc.org/github.com/cosmos72/gls

License

BSD 3-Clause License

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func GoID

func GoID() uintptr

return the current goroutine ID.

note that the returned value is DIFFERENT from most other goroutine libraries: this GoID() returns the address of the runtime.g struct, converted to uintptr. NOT the runtime.g.goid field returned by most other libraries.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL