zorldo

Goofing around with Ebiten
git clone git://bsandro.tech/zorldo
Log | Files | Refs | README

run_notsinglethread.go (2479B)


      1 // Copyright 2020 The Ebiten Authors
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 //go:build !ebitensinglethread && (darwin || freebsd || linux || windows) && !android && !ios
     16 // +build !ebitensinglethread
     17 // +build darwin freebsd linux windows
     18 // +build !android
     19 // +build !ios
     20 
     21 package glfw
     22 
     23 import (
     24 	"github.com/hajimehoshi/ebiten/v2/internal/driver"
     25 	"github.com/hajimehoshi/ebiten/v2/internal/graphicscommand"
     26 	"github.com/hajimehoshi/ebiten/v2/internal/thread"
     27 )
     28 
     29 func (u *UserInterface) Run(uicontext driver.UIContext) error {
     30 	u.context = uicontext
     31 
     32 	// Initialize the main thread first so the thread is available at u.run (#809).
     33 	u.t = thread.NewOSThread()
     34 	graphicscommand.SetMainThread(u.t)
     35 
     36 	ch := make(chan error, 1)
     37 	go func() {
     38 		defer func() {
     39 			_ = u.t.Call(func() error {
     40 				return thread.BreakLoop
     41 			})
     42 		}()
     43 
     44 		defer close(ch)
     45 
     46 		if err := u.t.Call(func() error {
     47 			return u.init()
     48 		}); err != nil {
     49 			ch <- err
     50 			return
     51 		}
     52 
     53 		if err := u.loop(); err != nil {
     54 			ch <- err
     55 			return
     56 		}
     57 	}()
     58 
     59 	u.setRunning(true)
     60 	u.t.Loop()
     61 	u.setRunning(false)
     62 	return <-ch
     63 }
     64 
     65 // runOnAnotherThreadFromMainThread is called from the main thread, and calls f on a new goroutine (thread).
     66 // runOnAnotherThreadFromMainThread creates a new nested main thread and runs the run loop.
     67 // u.t is updated to the new thread until runOnAnotherThreadFromMainThread is called.
     68 //
     69 // Inside f, another functions that must be called from the main thread can be called safely.
     70 func (u *UserInterface) runOnAnotherThreadFromMainThread(f func() error) error {
     71 	// As this function is called from the main thread, u.t should never be accessed and can be updated here.
     72 	t := u.t
     73 	defer func() {
     74 		u.t = t
     75 		graphicscommand.SetMainThread(t)
     76 	}()
     77 
     78 	u.t = thread.NewOSThread()
     79 	graphicscommand.SetMainThread(u.t)
     80 
     81 	var err error
     82 	go func() {
     83 		defer func() {
     84 			_ = u.t.Call(func() error {
     85 				return thread.BreakLoop
     86 			})
     87 		}()
     88 		err = f()
     89 	}()
     90 	u.t.Loop()
     91 	return err
     92 }