File tree Expand file tree Collapse file tree 5 files changed +178
-1
lines changed Expand file tree Collapse file tree 5 files changed +178
-1
lines changed Original file line number Diff line number Diff line change 1+ name : mainthread
2+
3+ on :
4+ push :
5+ branches : [ master ]
6+ pull_request :
7+ branches : [ master ]
8+
9+ jobs :
10+
11+ build :
12+ name : Build
13+ runs-on : ubuntu-latest
14+ steps :
15+
16+ - name : Set up Go 1.x
17+ uses : actions/setup-go@v2
18+ with :
19+ go-version : ^1.13
20+ id : go
21+
22+ - name : Check out code into the Go module directory
23+ uses : actions/checkout@v2
24+
25+ - name : Get dependencies
26+ run : |
27+ go get -v -t -d ./...
28+ - name : Test
29+ run : |
30+ go test -v -coverprofile=coverage.txt -covermode=atomic ./...
31+ - name : Upload coverage profile
32+ uses : codecov/codecov-action@v1
33+ with :
34+ token : ${{secrets.CODECOV_TOKEN}}
35+ file : coverage.txt
Original file line number Diff line number Diff line change 11# mainthread
2- scheduling events on main thread in Go
2+
3+ [ ![ PkgGoDev] ( https://pkg.go.dev/badge/golang.design/x/mainthread )] ( https://pkg.go.dev/golang.design/x/mainthread ) [ ![ Go Report Card] ( https://goreportcard.com/badge/golang.design/x/mainthread )] ( https://goreportcard.com/report/golang.design/x/mainthread )
4+ ![ mainthread] ( https://github.com/golang-design/mainthread/workflows/mainthread/badge.svg?branch=master )
5+
6+ Package mainthread schedules function calls on the main thread in Go.
7+
8+ ```
9+ import "golang.design/x/mainthread"
10+ ```
11+
12+ ## Quick Start
13+
14+ ``` go
15+ package main
16+
17+ import " golang.design/x/mainthread"
18+
19+ func main () {
20+ mainthread.Init (func () {
21+ mainthread.Call (func () {
22+ // ... runs on the main thread ...
23+ })
24+
25+ go func () {
26+ // ... runs concurrently ...
27+ }()
28+
29+ mainthread.Call (func () {
30+ // ... runs on the main thread ...
31+ })
32+ })
33+ }
34+ ```
35+
36+ ## License
37+
38+ GNU GPLv3 © ; 2020 The golang.design Initiative Authors
Original file line number Diff line number Diff line change 1+ module golang.design/x/mainthread
2+
3+ go 1.15
Original file line number Diff line number Diff line change 1+ // Copyright 2020 The golang.design Initiative Authors.
2+ // All rights reserved. Use of this source code is governed
3+ // by a GNU GPLv3 license that can be found in the LICENSE file.
4+
5+ package mainthread // import "golang.design/x/mainthread"
6+
7+ import "runtime"
8+
9+ // FIXME: can we do scheduling with zero overhead?
10+ var fqueue chan func ()
11+
12+ func init () {
13+ runtime .LockOSThread ()
14+
15+ // FIXME: what else can we do about queue size?
16+ fqueue = make (chan func (), runtime .GOMAXPROCS (0 ))
17+ }
18+
19+ // Init initializes the functionality for running arbitrary subsequent
20+ // functions on a main system thread.
21+ //
22+ // Init must be called in the main package.
23+ func Init (run func ()) {
24+ done := make (chan struct {})
25+ go func () {
26+ defer func () {
27+ // FIXME: do something about panicked f.
28+ recover ()
29+
30+ done <- struct {}{}
31+ }()
32+ run ()
33+ }()
34+
35+ for {
36+ select {
37+ case f := <- fqueue :
38+ f ()
39+ case <- done :
40+ return
41+ }
42+ }
43+ }
44+
45+ // Call calls f on the main thread and blocks until f finishes.
46+ func Call (f func ()) {
47+ done := make (chan struct {})
48+ fqueue <- func () {
49+ defer func () {
50+ // FIXME: do something about panicked f.
51+ recover ()
52+
53+ done <- struct {}{}
54+ }()
55+ f ()
56+ }
57+ <- done
58+ }
Original file line number Diff line number Diff line change 1+ // Copyright 2020 The golang.design Initiative Authors.
2+ // All rights reserved. Use of this source code is governed
3+ // by a GNU GPLv3 license that can be found in the LICENSE file.
4+
5+ package mainthread_test
6+
7+ import (
8+ "fmt"
9+ "testing"
10+
11+ "golang.design/x/mainthread"
12+ )
13+
14+ func TestMainthread (t * testing.T ) {
15+ mainthread .Init (func () {
16+ mainthread .Call (func () {
17+ // FIXME: how to test this function really runs on the main thread?
18+ })
19+ })
20+ }
21+
22+ func BenchmarkCall (b * testing.B ) {
23+ f1 := func () {}
24+ f2 := func () {}
25+
26+ mainthread .Init (func () {
27+ b .ResetTimer ()
28+ for i := 0 ; i < b .N ; i ++ {
29+ if i % 2 == 0 {
30+ mainthread .Call (f1 )
31+ } else {
32+ mainthread .Call (f2 )
33+ }
34+ }
35+ })
36+ }
37+
38+ func ExampleInit () {
39+ mainthread .Init (func () {
40+ mainthread .Call (func () {
41+ fmt .Println ("from main thread" )
42+ })
43+ })
44+ // Output: from main thread
45+ }
You can’t perform that action at this time.
0 commit comments