routine

package module
v1.0.2 Latest Latest
Warning

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

Go to latest
Published: Dec 9, 2022 License: MIT Imports: 9 Imported by: 7

README

routine

Build Status codecov Go doc

中文版

routine encapsulates and provides some easy-to-use, high-performance goroutine context access interfaces, which can help you access coroutine context information more elegantly, but you may also open Pandora's Box.

Introduce

The Golang language has been sparing no effort to shield developers from the concept of coroutine context from the beginning of its design, including the acquisition of coroutine goid, the state of the coroutine within the process, and the storage of coroutine context.

If you have used other languages such as C++/Java/..., then you must be familiar with ThreadLocal, and after starting to use Golang, you will definitely feel confused and distressed by the lack of convenient functions similar to ThreadLocal . Of course, you can choose to use Context, let it carry all the context information, appear in the first input parameter of all functions, and then shuttle around in your system.

The core goal of routine is to open up another path: to introduce goroutine local storage into the world of Golang , and at the same time expose the coroutine information to meet the needs of some people.

Usage & Demo

This chapter briefly introduces how to install and use the routine library.

Install

go get github.com/go-eden/routine

Use goid

The following code simply demonstrates the use of routine.Goid():

package main

import (
	"fmt"
	"github.com/go-eden/routine"
	"time"
)

func main() {
	go func() {
		time.Sleep(time.Second)
	}()
	goid := routine.Goid()
	fmt.Printf("curr goid: %d\n", goid)
}

In this example, the main function starts a new coroutine, so Goid() returns the main coroutine 1:

curr goid: 1

Use LocalStorage

The following code simply demonstrates NewLocalStorage(), Set(), Get(), and cross-coroutine propagation of LocalStorage:

package main

import (
	"fmt"
	"github.com/go-eden/routine"
	"time"
)

var nameVar = routine.NewLocalStorage()

func main() {
	nameVar.Set("hello world")
	fmt.Println("name: ", nameVar.Get())

	// other goroutine cannot read nameVar
	go func() {
		fmt.Println("name1: ", nameVar.Get())
	}()

	// but, the new goroutine could inherit/copy all local data from the current goroutine like this:
	routine.Go(func() {
		fmt.Println("name2: ", nameVar.Get())
	})

	// or, you could copy all local data manually
	ic := routine.BackupContext()
	go func() {
		routine.InheritContext(ic)
		fmt.Println("name3: ", nameVar.Get())
	}()

	time.Sleep(time.Second)
}

The results of the upper example are:

name:  hello world
name1:  <nil>
name3:  hello world
name2:  hello world

API

This chapter introduces in detail all the interfaces encapsulated by the routine library, as well as their core functions and implementation methods.

Goid() (id int64)

Get the goid of the current goroutine.

NewLocalStorage():

Create a new instance of LocalStorage, its design idea is very similar to the usage of ThreadLocal in other languages.

BackupContext() *ImmutableContext

Back up the local storage data of the current coroutine context. It is just an immutable structure that facilitates the transfer of context data.

InheritContext(ic *ImmutableContext)

Actively inherit the backed-up context local storage data, it will copy the data of other coroutines BackupContext() into the current coroutine context, thus supporting the contextual data propagation across coroutines.

Go(f func())

Start a new coroutine and automatically copy all the context local storage data of the current coroutine to the new coroutine. Its internal implementation consists of BackupContext() and InheritContext().

LocalStorage

Represents the context variable of the coroutine, and the supported functions include:

  • Get() (value interface{}): Get the variable value that has been set by the current coroutine.
  • Set(v interface{}) interface{}: Set the value of the context variable of the current coroutine, and return the old value that has been set before.
  • Del() (v interface{}): Delete the context variable value of the current coroutine and return the deleted old value.

Tip: The internal implementation of Get/Set/Del adopts a lock-free design. In most cases, its performance should be very stable and efficient.

Garbage Collection

Before the v1.0.0 version, routine will setup a backgrount timer to scan all go-routines intervally, and find the exited routine to clean the related LocalStorage data.

After the v1.0.0 version, routine will register a finalizer to listen the lifecycle of runtime.g.

After the coroutine exits, when runtime's GC running, the finalizer mechanism of runtime will actively remove the useless LocalStorage `Data clean up, So as to avoid memory leaks.

Thanks

The internal model internal/g is from other repos, mainly two functions:

License

MIT

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Go

func Go(f func())

Go start an new goroutine, and copy all local allStoreMap from current goroutine.

func Goid

func Goid() int64

Goid get the unique goid of the current routine.

func InheritContext

func InheritContext(ic *ImmutableContext)

InheritContext load the specified ImmutableContext instance into the local storage of current goroutine.

Types

type G added in v1.0.0

type G interface {

	// Goid returns g.goid
	Goid() int64

	// Labels returns g.labels, which's real type is map[string]string
	Labels() map[string]string

	// Status returns g.atomicstatus
	Status() GStatus
}

G defines some usefull api to access the underlying go-routine.

func GetG added in v1.0.0

func GetG() G

GetG returns the accessor of the current routine.

type GStatus added in v1.0.0

type GStatus uint32

GStatus represents the real status of runtime.g

const (
	GIdle      GStatus = 0 // see runtime._Gidle
	GRunnable  GStatus = 1 // see runtime._Grunnable
	GRunning   GStatus = 2 // see runtime._Grunning
	GSyscall   GStatus = 3 // see runtime._Gsyscall
	GWaiting   GStatus = 4 // see runtime._Gwaiting
	GMoribund  GStatus = 5 // see runtime._Gmoribund_unused
	GDead      GStatus = 6 // see runtime._Gdead
	GEnqueue   GStatus = 7 // see runtime._Genqueue_unused
	GCopystack GStatus = 8 // see runtime._Gcopystack
	GPreempted GStatus = 9 // see runtime._Gpreempted
)

type ImmutableContext

type ImmutableContext struct {
	// contains filtered or unexported fields
}

ImmutableContext represents all local allStoreMap of one goroutine.

func BackupContext

func BackupContext() *ImmutableContext

BackupContext copy all local allStoreMap into an ImmutableContext instance.

type LocalStorage

type LocalStorage interface {

	// Get returns the value in the current goroutine's local storage, if it was set before.
	Get() (value interface{})

	// Set copy the value into the current goroutine's local storage, and return the old value.
	Set(value interface{}) (oldValue interface{})

	// Del delete the value from the current goroutine's local storage, and return it.
	Del() (oldValue interface{})
}

LocalStorage provides goroutine-local variables.

func NewLocalStorage

func NewLocalStorage() LocalStorage

NewLocalStorage create and return a new LocalStorage instance.

Directories

Path Synopsis
internal
g
Package g exposes goroutine struct g to user space.
Package g exposes goroutine struct g to user space.

Jump to

Keyboard shortcuts

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