Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bump actions/checkout from 3 to 4 #33

Closed
wants to merge 22 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
753660d
Bump actions/setup-go from 3 to 4
timandy May 25, 2023
fb991a1
Update apt-get package cache before install qemu-user-static
timandy Jun 8, 2023
3d6f6a8
Use the latest version of hosted runners
timandy Jun 8, 2023
daabe0b
Fix golang ci file open errors
timandy Jun 8, 2023
0a17139
Bump github.com/stretchr/testify from 1.8.1 to 1.8.2
timandy May 25, 2023
03d4c37
Rename file future to future_task
timandy May 22, 2023
98c5db4
Rename type Future to FutureTask
timandy May 23, 2023
9825496
Support run a FutureTask and wrap a function to FutureTask instance
timandy May 22, 2023
6eb38fa
Add testcases for FutureCallable
timandy May 23, 2023
33da8d0
Add testcases for FutureTask
timandy May 22, 2023
de0373a
Add testcases for WrapTask
timandy May 23, 2023
4758f8a
Modify the documentation for the NewInheritableThreadLocal and NewInh…
timandy May 30, 2023
6beb202
Define Callable function alias
timandy May 22, 2023
5c27c3b
Support skip the first runtime panic stack automatically for RuntimeE…
timandy May 23, 2023
4355195
Fix print wrong created by function name on arch non-amd64
timandy May 25, 2023
33cf633
Add testcase to verify that errors are ignored when the task state al…
timandy May 25, 2023
8c20ffb
Modify testcase to verify the contents of standard output
timandy May 26, 2023
aca5bd7
Refactor anonymous method to struct method for clearer stack printing
timandy May 26, 2023
94e5f97
Update benchmark result
timandy May 25, 2023
bd26dab
Modify readme file
timandy May 25, 2023
2e87bfa
Modify change log
timandy May 30, 2023
a668e7b
Bump actions/checkout from 3 to 4
dependabot[bot] Sep 5, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 14 additions & 9 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,28 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout scm
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v3
uses: actions/setup-go@v4
with:
go-version-file: go.mod

- name: Lint
uses: golangci/golangci-lint-action@v3
with:
skip-pkg-cache: true
skip-build-cache: true

CodeQL:
needs: Lint
runs-on: ubuntu-latest
steps:
- name: Checkout scm
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v3
uses: actions/setup-go@v4
with:
go-version-file: go.mod

Expand Down Expand Up @@ -197,20 +200,20 @@ jobs:
- os: darwin
runs-on: macos-latest
- os: linux
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
- os: windows
runs-on: windows-latest
- os: freebsd
runs-on: macos-12
runs-on: macos-latest
- os: js
runs-on: ubuntu-latest

steps:
- name: Checkout scm
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v3
uses: actions/setup-go@v4
with:
go-version: ${{ matrix.go }}

Expand Down Expand Up @@ -239,7 +242,9 @@ jobs:

- name: 'Setup qemu-user-static on [linux] arch [armv6, armv7, arm64, mips, mipsle, mips64, mips64le, ppc64, ppc64le, riscv64, s390x]'
if: ${{ matrix.os == 'linux' && contains(fromJson('["armv6", "armv7", "arm64", "mips", "mipsle", "mips64", "mips64le", "ppc64", "ppc64le", "riscv64", "s390x"]'), matrix.arch) }}
run: sudo apt-get -y install qemu-user-static
run: |
sudo apt-get update
sudo apt-get -y install qemu-user-static

- name: 'Test on [linux] arch [armv6]'
if: ${{ matrix.os == 'linux' && contains(fromJson('["armv6"]'), matrix.arch) }}
Expand Down
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
<!--变更日志-->

# v1.1.2 Release notes

### Features

- Support capture values of `InheritableThreadLocal` by `WrapTask()`, `WrapWaitTask()` and `WrapWaitResultTask()` methods.
- Support run `FutureTask` by `FutureTask.Run()` method.
- Define function type `Runnable` and `FutureCallable`.

### Changes

- Rename type `Future` to `FutureTask`.
- Skip first runtime panic stack automatically for `RuntimeError`.

# Links

- Source code [https://github.com/timandy/routine/tree/v1.1.2](https://github.com/timandy/routine/tree/v1.1.2)

---

# v1.1.1 Release notes

### Features
Expand Down
59 changes: 49 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,19 @@ func main() {
fmt.Println("inheritableThreadLocal in goroutine:", inheritableThreadLocal.Get())
}()

// However, a new sub-coroutine can be started via the Go/GoWait/GoWaitResul function, and all inheritable variables of the current coroutine can be passed automatically.
// However, a new sub-coroutine can be started via the Go/GoWait/GoWaitResult function, and all inheritable variables of the current coroutine can be passed automatically.
routine.Go(func() {
fmt.Println("threadLocal in goroutine by Go:", threadLocal.Get())
fmt.Println("inheritableThreadLocal in goroutine by Go:", inheritableThreadLocal.Get())
})

// You can also create a task via the WrapTask/WrapWaitTask/WrapWaitResultTask function, and all inheritable variables of the current coroutine can be automatically captured.
task := routine.WrapTask(func() {
fmt.Println("threadLocal in task by WrapTask:", threadLocal.Get())
fmt.Println("inheritableThreadLocal in task by WrapTask:", inheritableThreadLocal.Get())
})
go task.Run()

// Wait for the sub-coroutine to finish executing.
time.Sleep(time.Second)
}
Expand All @@ -114,6 +121,8 @@ threadLocal in goroutine: <nil>
inheritableThreadLocal in goroutine: <nil>
threadLocal in goroutine by Go: <nil>
inheritableThreadLocal in goroutine by Go: Hello world2
threadLocal in task by WrapTask: <nil>
inheritableThreadLocal in task by WrapTask: Hello world2
```

# API
Expand All @@ -128,31 +137,61 @@ It can be obtained directly through assembly code under `386`, `amd64`, `armv6`,

## `NewThreadLocal() ThreadLocal`

Creates a new `ThreadLocal` instance with a stored default value of `nil`.
Create a new `ThreadLocal` instance with the initial value stored with `nil`.

## `NewThreadLocalWithInitial(supplier Supplier) ThreadLocal`

Creates a new `ThreadLocal` instance with default values stored by calling `supplier()`.
Create a new `ThreadLocal` instance with the initial value stored as the return value of the method `supplier()`.

## `NewInheritableThreadLocal() ThreadLocal`

Creates a new `ThreadLocal` instance with a stored default value of `nil`. When a new coroutine is started via `Go()`, `GoWait()` or `GoWaitResult()`, the value of the current coroutine is copied to the new coroutine.
Create a new `ThreadLocal` instance with the initial value stored with `nil`.
When a new coroutine is started via `Go()`, `GoWait()` or `GoWaitResult()`, the value of the current coroutine is copied to the new coroutine.
When a new task is created via `WrapTask()`, `WrapWaitTask()` or `WrapWaitResultTask()`, the value of the current coroutine is captured to the new task.

## `NewInheritableThreadLocalWithInitial(supplier Supplier) ThreadLocal`

Creates a new `ThreadLocal` instance with stored default values generated by calling `supplier()`. When a new coroutine is started via `Go()`, `GoWait()` or `GoWaitResult()`, the value of the current coroutine is copied to the new coroutine.
Create a new `ThreadLocal` instance with the initial value stored as the return value of the method `supplier()`.
When a new coroutine is started via `Go()`, `GoWait()` or `GoWaitResult()`, the value of the current coroutine is copied to the new coroutine.
When a new task is created via `WrapTask()`, `WrapWaitTask()` or `WrapWaitResultTask()`, the value of the current coroutine is captured to the new task.

## `WrapTask(fun Runnable) FutureTask`

Create a new task and capture the `inheritableThreadLocals` from the current goroutine.
This function returns a `FutureTask` instance, but the return task will not run automatically.
You can run it in a sub-goroutine or goroutine-pool by `FutureTask.Run()` method, wait by `FutureTask.Get()` or `FutureTask.GetWithTimeout()` method.
When the returned task run `panic` will be caught and error stack will be printed, the `panic` will be trigger again when calling `FutureTask.Get()` or `FutureTask.GetWithTimeout()` method.

## `WrapWaitTask(fun CancelRunnable) FutureTask`

Create a new task and capture the `inheritableThreadLocals` from the current goroutine.
This function returns a `FutureTask` instance, but the return task will not run automatically.
You can run it in a sub-goroutine or goroutine-pool by `FutureTask.Run()` method, wait by `FutureTask.Get()` or `FutureTask.GetWithTimeout()` method.
When the returned task run `panic` will be caught, the `panic` will be trigger again when calling `FutureTask.Get()` or `FutureTask.GetWithTimeout()` method.

## `WrapWaitResultTask(fun CancelCallable) FutureTask`

Create a new task and capture the `inheritableThreadLocals` from the current goroutine.
This function returns a `FutureTask` instance, but the return task will not run automatically.
You can run it in a sub-goroutine or goroutine-pool by `FutureTask.Run()` method, wait and get result by `FutureTask.Get()` or `FutureTask.GetWithTimeout()` method.
When the returned task run `panic` will be caught, the `panic` will be trigger again when calling `FutureTask.Get()` or `FutureTask.GetWithTimeout()` method.

## `Go(fun Runnable)`

Start a new coroutine and automatically copy all contextual `inheritableThreadLocals` data of the current coroutine to the new coroutine. Any `panic` while the child coroutine is executing will be caught and the stack automatically printed.
Start a new coroutine and automatically copy all contextual `inheritableThreadLocals` data of the current coroutine to the new coroutine.
Any `panic` while the child coroutine is executing will be caught and the stack automatically printed.

## `GoWait(fun CancelRunnable) Future`
## `GoWait(fun CancelRunnable) FutureTask`

Start a new coroutine and automatically copy all contextual `inheritableThreadLocals` data of the current coroutine to the new coroutine. You can wait for the sub-coroutine to finish executing through the `Future.Get()` or `Future.GetWithTimeout()` method that returns a value. Any `panic` while the child coroutine is executing will be caught and thrown again when `Future.Get()` or `Future.GetWithTimeout()` is called.
Start a new coroutine and automatically copy all contextual `inheritableThreadLocals` data of the current coroutine to the new coroutine.
You can wait for the sub-coroutine to finish executing through the `FutureTask.Get()` or `FutureTask.GetWithTimeout()` method that returns a value.
Any `panic` while the child coroutine is executing will be caught and thrown again when `FutureTask.Get()` or `FutureTask.GetWithTimeout()` is called.

## `GoWaitResult(fun CancelCallable) Future`
## `GoWaitResult(fun CancelCallable) FutureTask`

Start a new coroutine and automatically copy all contextual `inheritableThreadLocals` data of the current coroutine to the new coroutine. You can wait for the sub-coroutine to finish executing and get the return value through the `Future.Get()` or `Future.GetWithTimeout()` method of the return value. Any `panic` while the child coroutine is executing will be caught and thrown again when `Future.Get()` or `Future.GetWithTimeout()` is called.
Start a new coroutine and automatically copy all contextual `inheritableThreadLocals` data of the current coroutine to the new coroutine.
You can wait for the sub-coroutine to finish executing and get the return value through the `FutureTask.Get()` or `FutureTask.GetWithTimeout()` method of the return value.
Any `panic` while the child coroutine is executing will be caught and thrown again when `FutureTask.Get()` or `FutureTask.GetWithTimeout()` is called.

[More API Documentation](https://pkg.go.dev/github.com/timandy/routine#section-documentation)

Expand Down
59 changes: 49 additions & 10 deletions README_zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,19 @@ func main() {
fmt.Println("inheritableThreadLocal in goroutine:", inheritableThreadLocal.Get())
}()

// 但是,可以通过 Go/GoWait/GoWaitResul 函数启动一个新的子协程,当前协程的所有可继承变量都可以自动传递。
// 但是,可以通过 Go/GoWait/GoWaitResult 函数启动一个新的子协程,当前协程的所有可继承变量都可以自动传递。
routine.Go(func() {
fmt.Println("threadLocal in goroutine by Go:", threadLocal.Get())
fmt.Println("inheritableThreadLocal in goroutine by Go:", inheritableThreadLocal.Get())
})

// 也可以通过 WrapTask/WrapWaitTask/WrapWaitResultTask 函数创建一个任务,当前协程的所有可继承变量都可以被自动捕获。
task := routine.WrapTask(func() {
fmt.Println("threadLocal in task by WrapTask:", threadLocal.Get())
fmt.Println("inheritableThreadLocal in task by WrapTask:", inheritableThreadLocal.Get())
})
go task.Run()

// 等待子协程执行完。
time.Sleep(time.Second)
}
Expand All @@ -114,6 +121,8 @@ threadLocal in goroutine: <nil>
inheritableThreadLocal in goroutine: <nil>
threadLocal in goroutine by Go: <nil>
inheritableThreadLocal in goroutine by Go: Hello world2
threadLocal in task by WrapTask: <nil>
inheritableThreadLocal in task by WrapTask: Hello world2
```

# API文档
Expand All @@ -128,31 +137,61 @@ inheritableThreadLocal in goroutine by Go: Hello world2

## `NewThreadLocal() ThreadLocal`

创建一个新的`ThreadLocal`实例,其存储的默认值为`nil`。
创建一个新的`ThreadLocal`实例,其存储的初始值为`nil`。

## `NewThreadLocalWithInitial(supplier Supplier) ThreadLocal`

创建一个新的`ThreadLocal`实例,其存储的默认值会通过调用`supplier()`生成
创建一个新的`ThreadLocal`实例,其存储的初始值为方法`supplier()`的返回值

## `NewInheritableThreadLocal() ThreadLocal`

创建一个新的`ThreadLocal`实例,其存储的默认值为`nil`。当通过`Go()`、`GoWait()`或`GoWaitResult()`启动新协程时,当前协程的值会被复制到新协程。
创建一个新的`ThreadLocal`实例,其存储的初始值为`nil`。
当通过`Go()`、`GoWait()`或`GoWaitResult()`启动新协程时,当前协程的值会被复制到新协程。
当通过`WrapTask()`、`WrapWaitTask()`或`WrapWaitResultTask()`创建任务时,当前协程的值会被捕获。

## `NewInheritableThreadLocalWithInitial(supplier Supplier) ThreadLocal`

创建一个新的`ThreadLocal`实例,其存储的默认值会通过调用`supplier()`生成。当通过`Go()`、`GoWait()`或`GoWaitResult()`启动新协程时,当前协程的值会被复制到新协程。
创建一个新的`ThreadLocal`实例,其存储的初始值为方法`supplier()`的返回值。
当通过`Go()`、`GoWait()`或`GoWaitResult()`启动新协程时,当前协程的值会被复制到新协程。
当通过`WrapTask()`、`WrapWaitTask()`或`WrapWaitResultTask()`创建任务时,当前协程的值会被捕获。

## `WrapTask(fun Runnable) FutureTask`

创建一个新任务,并捕获当前协程的`inheritableThreadLocals`。
此函数返回一个`FutureTask`实例,但返回的任务不会自动运行。
你可以通过`FutureTask.Run()`方法在子协程或协程池中运行它,通过`FutureTask.Get()`或`FutureTask.GetWithTimeout()`方法等待任务执行完毕。
任务执行时的任何`panic`都会被捕获并打印错误堆栈,在调用`FutureTask.Get()`或`FutureTask.GetWithTimeout()`方法时`panic`会被再次抛出。

## `WrapWaitTask(fun CancelRunnable) FutureTask`

创建一个新任务,并捕获当前协程的`inheritableThreadLocals`。
此函数返回一个`FutureTask`实例,但返回的任务不会自动运行。
你可以通过`FutureTask.Run()`方法在子协程或协程池中运行它,通过`FutureTask.Get()`或`FutureTask.GetWithTimeout()`方法等待任务执行完毕。
任务执行时的任何`panic`都会被捕获,在调用`FutureTask.Get()`或`FutureTask.GetWithTimeout()`方法时`panic`会被再次抛出。

## `WrapWaitResultTask(fun CancelCallable) FutureTask`

创建一个新任务,并捕获当前协程的`inheritableThreadLocals`。
此函数返回一个`FutureTask`实例,但返回的任务不会自动运行。
你可以通过`FutureTask.Run()`方法在子协程或协程池中运行它,通过`FutureTask.Get()`或`FutureTask.GetWithTimeout()`方法等待任务执行完毕并获取结果。
任务执行时的任何`panic`都会被捕获,在调用`FutureTask.Get()`或`FutureTask.GetWithTimeout()`方法时`panic`会被再次抛出。

## `Go(fun Runnable)`

启动一个新的协程,同时自动将当前协程的全部上下文`inheritableThreadLocals`数据复制至新协程。子协程执行时的任何`panic`都会被捕获并自动打印堆栈。
启动一个新的协程,同时自动将当前协程的全部上下文`inheritableThreadLocals`数据复制至新协程。
子协程执行时的任何`panic`都会被捕获并自动打印堆栈。

## `GoWait(fun CancelRunnable) Future`
## `GoWait(fun CancelRunnable) FutureTask`

启动一个新的协程,同时自动将当前协程的全部上下文`inheritableThreadLocals`数据复制至新协程。可以通过返回值的`Future.Get()`或`Future.GetWithTimeout()`方法等待子协程执行完毕。子协程执行时的任何`panic`都会被捕获并在调用`Future.Get()`或`Future.GetWithTimeout()`时再次抛出。
启动一个新的协程,同时自动将当前协程的全部上下文`inheritableThreadLocals`数据复制至新协程。
可以通过返回值的`FutureTask.Get()`或`FutureTask.GetWithTimeout()`方法等待子协程执行完毕。
子协程执行时的任何`panic`都会被捕获并在调用`FutureTask.Get()`或`FutureTask.GetWithTimeout()`时再次抛出。

## `GoWaitResult(fun CancelCallable) Future`
## `GoWaitResult(fun CancelCallable) FutureTask`

启动一个新的协程,同时自动将当前协程的全部上下文`inheritableThreadLocals`数据复制至新协程。可以通过返回值的`Future.Get()`或`Future.GetWithTimeout()`方法等待子协程执行完毕并获取返回值。子协程执行时的任何`panic`都会被捕获并在调用`Future.Get()`或`Future.GetWithTimeout()`时再次抛出。
启动一个新的协程,同时自动将当前协程的全部上下文`inheritableThreadLocals`数据复制至新协程。
可以通过返回值的`FutureTask.Get()`或`FutureTask.GetWithTimeout()`方法等待子协程执行完毕并获取返回值。
子协程执行时的任何`panic`都会被捕获并在调用`FutureTask.Get()`或`FutureTask.GetWithTimeout()`时再次抛出。

[更多API文档](https://pkg.go.dev/github.com/timandy/routine#section-documentation)

Expand Down
8 changes: 4 additions & 4 deletions api_error_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,7 @@ func assertGoidGopc(t *testing.T, err RuntimeError) {

//===

// BenchmarkDebugStack-4 239652 5305 ns/op 1024 B/op 1 allocs/op
// BenchmarkDebugStack-8 301474 3400 ns/op 1024 B/op 1 allocs/op
func BenchmarkDebugStack(b *testing.B) {
b.ReportAllocs()
b.ResetTimer()
Expand All @@ -519,7 +519,7 @@ func BenchmarkDebugStack(b *testing.B) {
}
}

// BenchmarkRuntimeError-4 300091 4020 ns/op 2484 B/op 15 allocs/op
// BenchmarkRuntimeError-8 342477 3344 ns/op 2840 B/op 15 allocs/op
func BenchmarkRuntimeError(b *testing.B) {
b.ReportAllocs()
b.ResetTimer()
Expand All @@ -528,7 +528,7 @@ func BenchmarkRuntimeError(b *testing.B) {
}
}

// BenchmarkRuntimeErrorWithMessage-4 302037 3820 ns/op 2476 B/op 14 allocs/op
// BenchmarkRuntimeErrorWithMessage-8 337117 3300 ns/op 2872 B/op 15 allocs/op
func BenchmarkRuntimeErrorWithMessage(b *testing.B) {
b.ReportAllocs()
b.ResetTimer()
Expand All @@ -537,7 +537,7 @@ func BenchmarkRuntimeErrorWithMessage(b *testing.B) {
}
}

// BenchmarkRuntimeErrorWithMessageCause-4 326098 3679 ns/op 2652 B/op 14 allocs/op
// BenchmarkRuntimeErrorWithMessageCause-8 350422 3362 ns/op 2872 B/op 15 allocs/op
func BenchmarkRuntimeErrorWithMessageCause(b *testing.B) {
b.ReportAllocs()
b.ResetTimer()
Expand Down
Loading