all: use atomic.Bool instead of atomic.Store/LoadUint32

Updates #2422
This commit is contained in:
Hajime Hoshi 2024-04-29 19:02:23 +09:00
parent f2a18ed6ba
commit f34932151d
8 changed files with 50 additions and 82 deletions

View File

@ -25,18 +25,10 @@ import (
"github.com/hajimehoshi/ebiten/v2/internal/ui" "github.com/hajimehoshi/ebiten/v2/internal/ui"
) )
var screenFilterEnabled = int32(1) var screenFilterEnabled atomic.Bool
func isScreenFilterEnabled() bool { func init() {
return atomic.LoadInt32(&screenFilterEnabled) != 0 screenFilterEnabled.Store(true)
}
func setScreenFilterEnabled(enabled bool) {
v := int32(0)
if enabled {
v = 1
}
atomic.StoreInt32(&screenFilterEnabled, v)
} }
type gameForUI struct { type gameForUI struct {
@ -145,7 +137,7 @@ func (g *gameForUI) DrawFinalScreen(scale, offsetX, offsetY float64) {
} }
switch { switch {
case !isScreenFilterEnabled(), math.Floor(scale) == scale: case !screenFilterEnabled.Load(), math.Floor(scale) == scale:
op := &DrawImageOptions{} op := &DrawImageOptions{}
op.GeoM = geoM op.GeoM = geoM
g.screen.DrawImage(g.offscreen, op) g.screen.DrawImage(g.offscreen, op)

View File

@ -113,7 +113,7 @@ type nativeGamepadsDesktop struct {
enumObjectsCallback uintptr enumObjectsCallback uintptr
nativeWindow windows.HWND nativeWindow windows.HWND
deviceChanged int32 deviceChanged atomic.Bool
err error err error
} }
@ -537,11 +537,11 @@ func (g *nativeGamepadsDesktop) update(gamepads *gamepads) error {
g.origWndProc = h g.origWndProc = h
} }
if atomic.LoadInt32(&g.deviceChanged) != 0 { if g.deviceChanged.Load() {
if err := g.detectConnection(gamepads); err != nil { if err := g.detectConnection(gamepads); err != nil {
g.err = err g.err = err
} }
atomic.StoreInt32(&g.deviceChanged, 0) g.deviceChanged.Store(false)
} }
return nil return nil
@ -550,7 +550,7 @@ func (g *nativeGamepadsDesktop) update(gamepads *gamepads) error {
func (g *nativeGamepadsDesktop) wndProc(hWnd uintptr, uMsg uint32, wParam, lParam uintptr) uintptr { func (g *nativeGamepadsDesktop) wndProc(hWnd uintptr, uMsg uint32, wParam, lParam uintptr) uintptr {
switch uMsg { switch uMsg {
case _WM_DEVICECHANGE: case _WM_DEVICECHANGE:
atomic.StoreInt32(&g.deviceChanged, 1) g.deviceChanged.Store(true)
} }
return _CallWindowProcW(g.origWndProc, hWnd, uMsg, wParam, lParam) return _CallWindowProcW(g.origWndProc, hWnd, uMsg, wParam, lParam)
} }

View File

@ -43,14 +43,14 @@ const (
maxVertexFloatCount = MaxVertexCount * graphics.VertexFloatCount maxVertexFloatCount = MaxVertexCount * graphics.VertexFloatCount
) )
var vsyncEnabled int32 = 1 var vsyncEnabled atomic.Bool
func init() {
vsyncEnabled.Store(true)
}
func SetVsyncEnabled(enabled bool, graphicsDriver graphicsdriver.Graphics) { func SetVsyncEnabled(enabled bool, graphicsDriver graphicsdriver.Graphics) {
if enabled { vsyncEnabled.Store(enabled)
atomic.StoreInt32(&vsyncEnabled, 1)
} else {
atomic.StoreInt32(&vsyncEnabled, 0)
}
runOnRenderThread(func() { runOnRenderThread(func() {
graphicsDriver.SetVsyncEnabled(enabled) graphicsDriver.SetVsyncEnabled(enabled)
@ -185,7 +185,7 @@ func (q *commandQueue) Flush(graphicsDriver graphicsdriver.Graphics, endFrame bo
var sync bool var sync bool
// Disable asynchronous rendering when vsync is on, as this causes a rendering delay (#2822). // Disable asynchronous rendering when vsync is on, as this causes a rendering delay (#2822).
if endFrame && atomic.LoadInt32(&vsyncEnabled) != 0 { if endFrame && vsyncEnabled.Load() {
sync = true sync = true
} }
if !sync { if !sync {

View File

@ -65,13 +65,13 @@ type monitors struct {
m sync.Mutex m sync.Mutex
updateCalled int32 updateCalled atomic.Bool
} }
var theMonitors monitors var theMonitors monitors
func (m *monitors) append(ms []*Monitor) []*Monitor { func (m *monitors) append(ms []*Monitor) []*Monitor {
if atomic.LoadInt32(&m.updateCalled) == 0 { if !m.updateCalled.Load() {
panic("ui: (*monitors).update must be called before (*monitors).append is called") panic("ui: (*monitors).update must be called before (*monitors).append is called")
} }
@ -82,7 +82,7 @@ func (m *monitors) append(ms []*Monitor) []*Monitor {
} }
func (m *monitors) primaryMonitor() *Monitor { func (m *monitors) primaryMonitor() *Monitor {
if atomic.LoadInt32(&m.updateCalled) == 0 { if !m.updateCalled.Load() {
panic("ui: (*monitors).update must be called before (*monitors).primaryMonitor is called") panic("ui: (*monitors).update must be called before (*monitors).primaryMonitor is called")
} }
@ -179,6 +179,6 @@ func (m *monitors) update() error {
m.monitors = newMonitors m.monitors = newMonitors
m.m.Unlock() m.m.Unlock()
atomic.StoreInt32(&m.updateCalled, 1) m.updateCalled.Store(true)
return nil return nil
} }

View File

@ -75,10 +75,10 @@ type UserInterface struct {
err error err error
errM sync.Mutex errM sync.Mutex
isScreenClearedEveryFrame int32 isScreenClearedEveryFrame atomic.Bool
graphicsLibrary int32 graphicsLibrary int32
running int32 running atomic.Bool
terminated int32 terminated atomic.Bool
whiteImage *Image whiteImage *Image
@ -107,9 +107,9 @@ func Get() *UserInterface {
// newUserInterface must be called from the main thread. // newUserInterface must be called from the main thread.
func newUserInterface() (*UserInterface, error) { func newUserInterface() (*UserInterface, error) {
u := &UserInterface{ u := &UserInterface{
isScreenClearedEveryFrame: 1, graphicsLibrary: int32(GraphicsLibraryUnknown),
graphicsLibrary: int32(GraphicsLibraryUnknown),
} }
u.isScreenClearedEveryFrame.Store(true)
u.whiteImage = u.NewImage(3, 3, atlas.ImageTypeRegular) u.whiteImage = u.NewImage(3, 3, atlas.ImageTypeRegular)
pix := make([]byte, 4*u.whiteImage.width*u.whiteImage.height) pix := make([]byte, 4*u.whiteImage.width*u.whiteImage.height)
@ -196,15 +196,11 @@ func (u *UserInterface) setError(err error) {
} }
func (u *UserInterface) IsScreenClearedEveryFrame() bool { func (u *UserInterface) IsScreenClearedEveryFrame() bool {
return atomic.LoadInt32(&u.isScreenClearedEveryFrame) != 0 return u.isScreenClearedEveryFrame.Load()
} }
func (u *UserInterface) SetScreenClearedEveryFrame(cleared bool) { func (u *UserInterface) SetScreenClearedEveryFrame(cleared bool) {
v := int32(0) u.isScreenClearedEveryFrame.Store(cleared)
if cleared {
v = 1
}
atomic.StoreInt32(&u.isScreenClearedEveryFrame, v)
} }
func (u *UserInterface) setGraphicsLibrary(library GraphicsLibrary) { func (u *UserInterface) setGraphicsLibrary(library GraphicsLibrary) {
@ -216,21 +212,17 @@ func (u *UserInterface) GraphicsLibrary() GraphicsLibrary {
} }
func (u *UserInterface) isRunning() bool { func (u *UserInterface) isRunning() bool {
return atomic.LoadInt32(&u.running) != 0 && !u.isTerminated() return u.running.Load() && !u.isTerminated()
} }
func (u *UserInterface) setRunning(running bool) { func (u *UserInterface) setRunning(running bool) {
if running { u.running.Store(running)
atomic.StoreInt32(&u.running, 1)
} else {
atomic.StoreInt32(&u.running, 0)
}
} }
func (u *UserInterface) isTerminated() bool { func (u *UserInterface) isTerminated() bool {
return atomic.LoadInt32(&u.terminated) != 0 return u.terminated.Load()
} }
func (u *UserInterface) setTerminated() { func (u *UserInterface) setTerminated() {
atomic.StoreInt32(&u.terminated, 1) u.terminated.Store(true)
} }

View File

@ -40,7 +40,6 @@ var (
func (u *UserInterface) init() error { func (u *UserInterface) init() error {
u.userInterfaceImpl = userInterfaceImpl{ u.userInterfaceImpl = userInterfaceImpl{
foreground: 1,
graphicsLibraryInitCh: make(chan struct{}), graphicsLibraryInitCh: make(chan struct{}),
errCh: make(chan error), errCh: make(chan error),
@ -48,6 +47,7 @@ func (u *UserInterface) init() error {
outsideWidth: 640, outsideWidth: 640,
outsideHeight: 480, outsideHeight: 480,
} }
u.foreground.Store(true)
return nil return nil
} }
@ -89,7 +89,7 @@ type userInterfaceImpl struct {
outsideWidth float64 outsideWidth float64
outsideHeight float64 outsideHeight float64
foreground int32 foreground atomic.Bool
errCh chan error errCh chan error
context *context context *context
@ -104,11 +104,7 @@ type userInterfaceImpl struct {
} }
func (u *UserInterface) SetForeground(foreground bool) error { func (u *UserInterface) SetForeground(foreground bool) error {
var v int32 u.foreground.Store(foreground)
if foreground {
v = 1
}
atomic.StoreInt32(&u.foreground, v)
if foreground { if foreground {
return hook.ResumeAudio() return hook.ResumeAudio()
@ -220,7 +216,7 @@ func (u *UserInterface) SetFullscreen(fullscreen bool) {
} }
func (u *UserInterface) IsFocused() bool { func (u *UserInterface) IsFocused() bool {
return atomic.LoadInt32(&u.foreground) != 0 return u.foreground.Load()
} }
func (u *UserInterface) IsRunnableOnUnfocused() bool { func (u *UserInterface) IsRunnableOnUnfocused() bool {

38
run.go
View File

@ -149,7 +149,7 @@ func CurrentFPS() float64 {
} }
var ( var (
isRunGameEnded_ = int32(0) isRunGameEnded_ atomic.Bool
) )
// SetScreenClearedEveryFrame enables or disables the clearing of the screen at the beginning of each frame. // SetScreenClearedEveryFrame enables or disables the clearing of the screen at the beginning of each frame.
@ -179,7 +179,7 @@ func IsScreenClearedEveryFrame() bool {
// //
// Deprecated: as of v2.5. Use FinalScreenDrawer instead. // Deprecated: as of v2.5. Use FinalScreenDrawer instead.
func SetScreenFilterEnabled(enabled bool) { func SetScreenFilterEnabled(enabled bool) {
setScreenFilterEnabled(enabled) screenFilterEnabled.Store(enabled)
} }
// IsScreenFilterEnabled returns true if Ebitengine's "screen" filter is enabled. // IsScreenFilterEnabled returns true if Ebitengine's "screen" filter is enabled.
@ -188,7 +188,7 @@ func SetScreenFilterEnabled(enabled bool) {
// //
// Deprecated: as of v2.5. // Deprecated: as of v2.5.
func IsScreenFilterEnabled() bool { func IsScreenFilterEnabled() bool {
return isScreenFilterEnabled() return screenFilterEnabled.Load()
} }
// Termination is a special error which indicates Game termination without error. // Termination is a special error which indicates Game termination without error.
@ -309,17 +309,13 @@ type RunGameOptions struct {
// //
// Don't call RunGame or RunGameWithOptions twice or more in one process. // Don't call RunGame or RunGameWithOptions twice or more in one process.
func RunGameWithOptions(game Game, options *RunGameOptions) error { func RunGameWithOptions(game Game, options *RunGameOptions) error {
defer atomic.StoreInt32(&isRunGameEnded_, 1) defer isRunGameEnded_.Store(true)
initializeWindowPositionIfNeeded(WindowSize()) initializeWindowPositionIfNeeded(WindowSize())
op := toUIRunOptions(options) op := toUIRunOptions(options)
// This is necessary to change the result of IsScreenTransparent. // This is necessary to change the result of IsScreenTransparent.
if op.ScreenTransparent { screenTransparent.Store(op.ScreenTransparent)
atomic.StoreInt32(&screenTransparent, 1)
} else {
atomic.StoreInt32(&screenTransparent, 0)
}
g := newGameForUI(game, op.ScreenTransparent) g := newGameForUI(game, op.ScreenTransparent)
if err := ui.Get().Run(g, op); err != nil { if err := ui.Get().Run(g, op); err != nil {
@ -333,7 +329,7 @@ func RunGameWithOptions(game Game, options *RunGameOptions) error {
} }
func isRunGameEnded() bool { func isRunGameEnded() bool {
return atomic.LoadInt32(&isRunGameEnded_) != 0 return isRunGameEnded_.Load()
} }
// ScreenSizeInFullscreen returns the size in device-independent pixels when the game is fullscreen. // ScreenSizeInFullscreen returns the size in device-independent pixels when the game is fullscreen.
@ -640,7 +636,7 @@ func IsScreenTransparent() bool {
if !ui.IsScreenTransparentAvailable() { if !ui.IsScreenTransparentAvailable() {
return false return false
} }
return atomic.LoadInt32(&screenTransparent) != 0 return screenTransparent.Load()
} }
// SetScreenTransparent sets the state if the window is transparent. // SetScreenTransparent sets the state if the window is transparent.
@ -653,14 +649,10 @@ func IsScreenTransparent() bool {
// //
// Deprecated: as of v2.5. Use RunGameWithOptions instead. // Deprecated: as of v2.5. Use RunGameWithOptions instead.
func SetScreenTransparent(transparent bool) { func SetScreenTransparent(transparent bool) {
if transparent { screenTransparent.Store(transparent)
atomic.StoreInt32(&screenTransparent, 1)
} else {
atomic.StoreInt32(&screenTransparent, 0)
}
} }
var screenTransparent int32 = 0 var screenTransparent atomic.Bool
// SetInitFocused sets whether the application is focused on show. // SetInitFocused sets whether the application is focused on show.
// The default value is true, i.e., the application is focused. // The default value is true, i.e., the application is focused.
@ -673,14 +665,10 @@ var screenTransparent int32 = 0
// //
// Deprecated: as of v2.5. Use RunGameWithOptions instead. // Deprecated: as of v2.5. Use RunGameWithOptions instead.
func SetInitFocused(focused bool) { func SetInitFocused(focused bool) {
if focused { initUnfocused.Store(!focused)
atomic.StoreInt32(&initUnfocused, 0)
} else {
atomic.StoreInt32(&initUnfocused, 1)
}
} }
var initUnfocused int32 = 0 var initUnfocused atomic.Bool
func toUIRunOptions(options *RunGameOptions) *ui.RunOptions { func toUIRunOptions(options *RunGameOptions) *ui.RunOptions {
const ( const (
@ -690,8 +678,8 @@ func toUIRunOptions(options *RunGameOptions) *ui.RunOptions {
if options == nil { if options == nil {
return &ui.RunOptions{ return &ui.RunOptions{
InitUnfocused: atomic.LoadInt32(&initUnfocused) != 0, InitUnfocused: initUnfocused.Load(),
ScreenTransparent: atomic.LoadInt32(&screenTransparent) != 0, ScreenTransparent: screenTransparent.Load(),
X11ClassName: defaultX11ClassName, X11ClassName: defaultX11ClassName,
X11InstanceName: defaultX11InstanceName, X11InstanceName: defaultX11InstanceName,
} }

View File

@ -155,16 +155,16 @@ func WindowPosition() (x, y int) {
// //
// SetWindowPosition is concurrent-safe. // SetWindowPosition is concurrent-safe.
func SetWindowPosition(x, y int) { func SetWindowPosition(x, y int) {
atomic.StoreUint32(&windowPositionSetExplicitly, 1) windowPositionSetExplicitly.Store(true)
ui.Get().Window().SetPosition(x, y) ui.Get().Window().SetPosition(x, y)
} }
var ( var (
windowPositionSetExplicitly uint32 windowPositionSetExplicitly atomic.Bool
) )
func initializeWindowPositionIfNeeded(width, height int) { func initializeWindowPositionIfNeeded(width, height int) {
if atomic.LoadUint32(&windowPositionSetExplicitly) == 0 { if !windowPositionSetExplicitly.Load() {
sw, sh := ui.Get().Monitor().Size() sw, sh := ui.Get().Monitor().Size()
x, y := ui.InitialWindowPosition(sw, sh, width, height) x, y := ui.InitialWindowPosition(sw, sh, width, height)
ui.Get().Window().SetPosition(x, y) ui.Get().Window().SetPosition(x, y)