thread: Use an error value instead of context.Context

This commit is contained in:
Hajime Hoshi 2020-08-30 02:10:49 +09:00
parent 9e678b9ecf
commit 349faa0f34
3 changed files with 31 additions and 34 deletions

View File

@ -15,7 +15,7 @@
package thread
import (
"context"
"errors"
)
// Thread represents an OS thread.
@ -34,20 +34,20 @@ func New() *Thread {
}
}
// Loop starts the thread loop.
// BreakLoop represents an termination of the loop.
var BreakLoop = errors.New("break loop")
// Loop starts the thread loop until a posted function returns BreakLoop.
//
// Loop must be called on the thread.
//
// Loop can be called multiple times.
func (t *Thread) Loop(context context.Context) {
loop:
for {
select {
case f := <-t.funcs:
t.results <- f()
case <-context.Done():
break loop
func (t *Thread) Loop() {
for f := range t.funcs {
err := f()
if err == BreakLoop {
t.results <- nil
return
}
t.results <- err
}
}
@ -55,6 +55,8 @@ loop:
//
// Do not call this from the same thread. This would block forever.
//
// If f returns BreakLoop, Loop returns.
//
// Call blocks if Loop is not called.
func (t *Thread) Call(f func() error) error {
t.funcs <- f

View File

@ -20,7 +20,6 @@
package glfw
import (
"context"
"fmt"
"image"
"os"
@ -602,14 +601,11 @@ func (u *UserInterface) Run(uicontext driver.UIContext) error {
u.t = thread.New()
u.Graphics().SetThread(u.t)
ctx, cancel := context.WithCancel(context.Background())
ch := make(chan error, 1)
go func() {
defer func() {
_ = u.t.Call(func() error {
cancel()
return nil
return thread.BreakLoop
})
}()
@ -620,7 +616,7 @@ func (u *UserInterface) Run(uicontext driver.UIContext) error {
}()
u.setRunning(true)
u.t.Loop(ctx)
u.t.Loop()
u.setRunning(false)
return <-ch
}

View File

@ -84,24 +84,17 @@ func (u *UserInterface) Update() error {
}
renderCh <- struct{}{}
ctx, cancel := context.WithCancel(context.Background())
go func() {
<-renderEndCh
if u.t != nil {
// If there is a (main) thread, ensure that cancel is called after every other task is done.
u.t.Call(func() error {
cancel()
return nil
})
} else {
cancel()
}
}()
if u.Graphics().IsGL() {
if u.glWorker == nil {
panic("mobile: glWorker must be initialized but not")
}
ctx, cancel := context.WithCancel(context.Background())
go func() {
<-renderEndCh
cancel()
}()
workAvailable := u.glWorker.WorkAvailable()
loop:
for {
@ -118,9 +111,15 @@ func (u *UserInterface) Update() error {
}
}
return nil
} else {
u.t.Loop(ctx)
}
go func() {
<-renderEndCh
u.t.Call(func() error {
return thread.BreakLoop
})
}()
u.t.Loop()
return nil
}