mirror of
https://github.com/giongto35/cloud-game.git
synced 2026-01-23 02:34:42 +00:00
Main thread lock refactoring (#367)
Use slim main thread locking function for macOS instead of a lib.
This commit is contained in:
parent
af98bddb14
commit
e53cf45fa7
11 changed files with 85 additions and 45 deletions
|
|
@ -41,5 +41,5 @@ func run() {
|
|||
}
|
||||
|
||||
func main() {
|
||||
thread.MainWrapMaybe(run)
|
||||
thread.Wrap(run)
|
||||
}
|
||||
|
|
|
|||
1
go.mod
1
go.mod
|
|
@ -4,7 +4,6 @@ go 1.13
|
|||
|
||||
require (
|
||||
github.com/cavaliercoder/grab v1.0.1-0.20201108051000-98a5bfe305ec
|
||||
github.com/faiface/mainthread v0.0.0-20171120011319-8b78f0a41ae3
|
||||
github.com/fsnotify/fsnotify v1.5.1
|
||||
github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6
|
||||
github.com/gofrs/flock v0.8.1
|
||||
|
|
|
|||
2
go.sum
2
go.sum
|
|
@ -60,8 +60,6 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
|
|||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/faiface/mainthread v0.0.0-20171120011319-8b78f0a41ae3 h1:baVdMKlASEHrj19iqjARrPbaRisD7EuZEVJj6ZMLl1Q=
|
||||
github.com/faiface/mainthread v0.0.0-20171120011319-8b78f0a41ae3/go.mod h1:VEPNJUlxl5KdWjDvz6Q1l+rJlxF2i6xqDeGuGAxa87M=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI=
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ func Init(cfg Config) {
|
|||
}
|
||||
|
||||
// In OSX 10.14+ window creation and context creation must happen in the main thread
|
||||
thread.MainMaybe(createWindow)
|
||||
thread.Main(createWindow)
|
||||
|
||||
BindContext()
|
||||
|
||||
|
|
@ -77,7 +77,7 @@ func Deinit() {
|
|||
log.Printf("[SDL] [OpenGL] deinitialization...")
|
||||
destroyFramebuffer()
|
||||
// In OSX 10.14+ window deletion must happen in the main thread
|
||||
thread.MainMaybe(destroyWindow)
|
||||
thread.Main(destroyWindow)
|
||||
sdl.Quit()
|
||||
log.Printf("[SDL] [OpenGL] deinitialized (%v, %v)", sdl.GetError(), getDriverError())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -594,7 +594,7 @@ func toggleMultitap() {
|
|||
|
||||
func nanoarchShutdown() {
|
||||
if usesLibCo {
|
||||
thread.MainMaybe(func() {
|
||||
thread.Main(func() {
|
||||
C.bridge_execute(retroUnloadGame)
|
||||
C.bridge_execute(retroDeinit)
|
||||
if video.isGl {
|
||||
|
|
@ -603,7 +603,7 @@ func nanoarchShutdown() {
|
|||
})
|
||||
} else {
|
||||
if video.isGl {
|
||||
thread.MainMaybe(func() {
|
||||
thread.Main(func() {
|
||||
// running inside a go routine, lock the thread to make sure the OpenGL context stays current
|
||||
runtime.LockOSThread()
|
||||
graphics.BindContext()
|
||||
|
|
@ -612,7 +612,7 @@ func nanoarchShutdown() {
|
|||
C.bridge_retro_unload_game(retroUnloadGame)
|
||||
C.bridge_retro_deinit(retroDeinit)
|
||||
if video.isGl {
|
||||
thread.MainMaybe(func() {
|
||||
thread.Main(func() {
|
||||
deinitVideo()
|
||||
runtime.UnlockOSThread()
|
||||
})
|
||||
|
|
|
|||
45
pkg/thread/mainthread_darwin.go
Normal file
45
pkg/thread/mainthread_darwin.go
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
package thread
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type fun struct {
|
||||
fn func()
|
||||
done chan struct{}
|
||||
}
|
||||
|
||||
var dPool = sync.Pool{New: func() interface{} { return make(chan struct{}) }}
|
||||
var fq = make(chan fun, runtime.GOMAXPROCS(0))
|
||||
|
||||
func init() {
|
||||
runtime.LockOSThread()
|
||||
}
|
||||
|
||||
// Run is a wrapper for the main function.
|
||||
// Run returns when run (argument) function finishes.
|
||||
func Run(run func()) {
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
run()
|
||||
done <- struct{}{}
|
||||
}()
|
||||
for {
|
||||
select {
|
||||
case f := <-fq:
|
||||
f.fn()
|
||||
f.done <- struct{}{}
|
||||
case <-done:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Call queues function f on the main thread and blocks until the function f finishes.
|
||||
func Call(f func()) {
|
||||
done := dPool.Get().(chan struct{})
|
||||
defer dPool.Put(done)
|
||||
fq <- fun{fn: f, done: done}
|
||||
<-done
|
||||
}
|
||||
16
pkg/thread/mainthread_darwin_test.go
Normal file
16
pkg/thread/mainthread_darwin_test.go
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
package thread
|
||||
|
||||
import "testing"
|
||||
|
||||
func init() {
|
||||
runtime.LockOSThread()
|
||||
}
|
||||
|
||||
func TestMainThread(t *testing.T) {
|
||||
value := 0
|
||||
fn := func() { value = 1 }
|
||||
Main(fn)
|
||||
if value != 1 {
|
||||
t.Errorf("wrong value %v", value)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,32 +1,7 @@
|
|||
// This package used for locking goroutines to
|
||||
// the main OS thread.
|
||||
// See: https://github.com/golang/go/wiki/LockOSThread
|
||||
//go:build !darwin
|
||||
// +build !darwin
|
||||
|
||||
package thread
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
|
||||
"github.com/faiface/mainthread"
|
||||
)
|
||||
|
||||
var isMacOs = runtime.GOOS == "darwin"
|
||||
|
||||
// MainWrapMaybe enables functions to be executed in the main thread.
|
||||
// Enabled for macOS only.
|
||||
func MainWrapMaybe(f func()) {
|
||||
if isMacOs {
|
||||
mainthread.Run(f)
|
||||
} else {
|
||||
f()
|
||||
}
|
||||
}
|
||||
|
||||
// MainMaybe calls a function on the main thread.
|
||||
// Enabled for macOS only.
|
||||
func MainMaybe(f func()) {
|
||||
if isMacOs {
|
||||
mainthread.Call(f)
|
||||
} else {
|
||||
f()
|
||||
}
|
||||
}
|
||||
func Wrap(f func()) { f() }
|
||||
func Main(f func()) { f() }
|
||||
|
|
|
|||
10
pkg/thread/thread_darwin.go
Normal file
10
pkg/thread/thread_darwin.go
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
// This package used for locking goroutines to
|
||||
// the main OS thread.
|
||||
// See: https://github.com/golang/go/wiki/LockOSThread
|
||||
package thread
|
||||
|
||||
// Wrap enables functions to be executed in the main thread.
|
||||
func Wrap(f func()) { Run(f) }
|
||||
|
||||
// Main calls a function on the main thread.
|
||||
func Main(f func()) { Call(f) }
|
||||
|
|
@ -62,7 +62,7 @@ func TestMain(m *testing.M) {
|
|||
flag.StringVar(&outputPath, "outputPath", "./", "Output path for generated files")
|
||||
flag.BoolVar(&autoGlContext, "autoGlContext", false, "Set auto GL context choose for headless machines")
|
||||
|
||||
thread.MainWrapMaybe(func() { os.Exit(m.Run()) })
|
||||
thread.Wrap(func() { os.Exit(m.Run()) })
|
||||
}
|
||||
|
||||
func TestRoom(t *testing.T) {
|
||||
|
|
@ -130,7 +130,7 @@ func TestRoomWithGL(t *testing.T) {
|
|||
time.Sleep(2 * time.Second)
|
||||
}
|
||||
|
||||
thread.MainMaybe(run)
|
||||
thread.Main(run)
|
||||
}
|
||||
|
||||
func TestAllEmulatorRooms(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -17,10 +17,7 @@ func New(conf worker.Config) (services service.Group) {
|
|||
mainHandler := NewHandler(conf, httpSrv.Addr)
|
||||
mainHandler.Prepare()
|
||||
|
||||
services.Add(
|
||||
httpSrv,
|
||||
mainHandler,
|
||||
)
|
||||
services.Add(httpSrv, mainHandler)
|
||||
if conf.Worker.Monitoring.IsEnabled() {
|
||||
services.Add(monitoring.New(conf.Worker.Monitoring, httpSrv.GetHost(), "worker"))
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue