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"
)
var screenFilterEnabled = int32(1)
var screenFilterEnabled atomic.Bool
func isScreenFilterEnabled() bool {
return atomic.LoadInt32(&screenFilterEnabled) != 0
}
func setScreenFilterEnabled(enabled bool) {
v := int32(0)
if enabled {
v = 1
}
atomic.StoreInt32(&screenFilterEnabled, v)
func init() {
screenFilterEnabled.Store(true)
}
type gameForUI struct {
@ -145,7 +137,7 @@ func (g *gameForUI) DrawFinalScreen(scale, offsetX, offsetY float64) {
}
switch {
case !isScreenFilterEnabled(), math.Floor(scale) == scale:
case !screenFilterEnabled.Load(), math.Floor(scale) == scale:
op := &DrawImageOptions{}
op.GeoM = geoM
g.screen.DrawImage(g.offscreen, op)

View File

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

View File

@ -43,14 +43,14 @@ const (
maxVertexFloatCount = MaxVertexCount * graphics.VertexFloatCount
)
var vsyncEnabled int32 = 1
var vsyncEnabled atomic.Bool
func init() {
vsyncEnabled.Store(true)
}
func SetVsyncEnabled(enabled bool, graphicsDriver graphicsdriver.Graphics) {
if enabled {
atomic.StoreInt32(&vsyncEnabled, 1)
} else {
atomic.StoreInt32(&vsyncEnabled, 0)
}
vsyncEnabled.Store(enabled)
runOnRenderThread(func() {
graphicsDriver.SetVsyncEnabled(enabled)
@ -185,7 +185,7 @@ func (q *commandQueue) Flush(graphicsDriver graphicsdriver.Graphics, endFrame bo
var sync bool
// 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
}
if !sync {

View File

@ -65,13 +65,13 @@ type monitors struct {
m sync.Mutex
updateCalled int32
updateCalled atomic.Bool
}
var theMonitors monitors
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")
}
@ -82,7 +82,7 @@ func (m *monitors) append(ms []*Monitor) []*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")
}
@ -179,6 +179,6 @@ func (m *monitors) update() error {
m.monitors = newMonitors
m.m.Unlock()
atomic.StoreInt32(&m.updateCalled, 1)
m.updateCalled.Store(true)
return nil
}

View File

@ -75,10 +75,10 @@ type UserInterface struct {
err error
errM sync.Mutex
isScreenClearedEveryFrame int32
isScreenClearedEveryFrame atomic.Bool
graphicsLibrary int32
running int32
terminated int32
running atomic.Bool
terminated atomic.Bool
whiteImage *Image
@ -107,9 +107,9 @@ func Get() *UserInterface {
// newUserInterface must be called from the main thread.
func newUserInterface() (*UserInterface, error) {
u := &UserInterface{
isScreenClearedEveryFrame: 1,
graphicsLibrary: int32(GraphicsLibraryUnknown),
graphicsLibrary: int32(GraphicsLibraryUnknown),
}
u.isScreenClearedEveryFrame.Store(true)
u.whiteImage = u.NewImage(3, 3, atlas.ImageTypeRegular)
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 {
return atomic.LoadInt32(&u.isScreenClearedEveryFrame) != 0
return u.isScreenClearedEveryFrame.Load()
}
func (u *UserInterface) SetScreenClearedEveryFrame(cleared bool) {
v := int32(0)
if cleared {
v = 1
}
atomic.StoreInt32(&u.isScreenClearedEveryFrame, v)
u.isScreenClearedEveryFrame.Store(cleared)
}
func (u *UserInterface) setGraphicsLibrary(library GraphicsLibrary) {
@ -216,21 +212,17 @@ func (u *UserInterface) GraphicsLibrary() GraphicsLibrary {
}
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) {
if running {
atomic.StoreInt32(&u.running, 1)
} else {
atomic.StoreInt32(&u.running, 0)
}
u.running.Store(running)
}
func (u *UserInterface) isTerminated() bool {
return atomic.LoadInt32(&u.terminated) != 0
return u.terminated.Load()
}
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 {
u.userInterfaceImpl = userInterfaceImpl{
foreground: 1,
graphicsLibraryInitCh: make(chan struct{}),
errCh: make(chan error),
@ -48,6 +47,7 @@ func (u *UserInterface) init() error {
outsideWidth: 640,
outsideHeight: 480,
}
u.foreground.Store(true)
return nil
}
@ -89,7 +89,7 @@ type userInterfaceImpl struct {
outsideWidth float64
outsideHeight float64
foreground int32
foreground atomic.Bool
errCh chan error
context *context
@ -104,11 +104,7 @@ type userInterfaceImpl struct {
}
func (u *UserInterface) SetForeground(foreground bool) error {
var v int32
if foreground {
v = 1
}
atomic.StoreInt32(&u.foreground, v)
u.foreground.Store(foreground)
if foreground {
return hook.ResumeAudio()
@ -220,7 +216,7 @@ func (u *UserInterface) SetFullscreen(fullscreen bool) {
}
func (u *UserInterface) IsFocused() bool {
return atomic.LoadInt32(&u.foreground) != 0
return u.foreground.Load()
}
func (u *UserInterface) IsRunnableOnUnfocused() bool {

38
run.go
View File

@ -149,7 +149,7 @@ func CurrentFPS() float64 {
}
var (
isRunGameEnded_ = int32(0)
isRunGameEnded_ atomic.Bool
)
// 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.
func SetScreenFilterEnabled(enabled bool) {
setScreenFilterEnabled(enabled)
screenFilterEnabled.Store(enabled)
}
// IsScreenFilterEnabled returns true if Ebitengine's "screen" filter is enabled.
@ -188,7 +188,7 @@ func SetScreenFilterEnabled(enabled bool) {
//
// Deprecated: as of v2.5.
func IsScreenFilterEnabled() bool {
return isScreenFilterEnabled()
return screenFilterEnabled.Load()
}
// 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.
func RunGameWithOptions(game Game, options *RunGameOptions) error {
defer atomic.StoreInt32(&isRunGameEnded_, 1)
defer isRunGameEnded_.Store(true)
initializeWindowPositionIfNeeded(WindowSize())
op := toUIRunOptions(options)
// This is necessary to change the result of IsScreenTransparent.
if op.ScreenTransparent {
atomic.StoreInt32(&screenTransparent, 1)
} else {
atomic.StoreInt32(&screenTransparent, 0)
}
screenTransparent.Store(op.ScreenTransparent)
g := newGameForUI(game, op.ScreenTransparent)
if err := ui.Get().Run(g, op); err != nil {
@ -333,7 +329,7 @@ func RunGameWithOptions(game Game, options *RunGameOptions) error {
}
func isRunGameEnded() bool {
return atomic.LoadInt32(&isRunGameEnded_) != 0
return isRunGameEnded_.Load()
}
// ScreenSizeInFullscreen returns the size in device-independent pixels when the game is fullscreen.
@ -640,7 +636,7 @@ func IsScreenTransparent() bool {
if !ui.IsScreenTransparentAvailable() {
return false
}
return atomic.LoadInt32(&screenTransparent) != 0
return screenTransparent.Load()
}
// SetScreenTransparent sets the state if the window is transparent.
@ -653,14 +649,10 @@ func IsScreenTransparent() bool {
//
// Deprecated: as of v2.5. Use RunGameWithOptions instead.
func SetScreenTransparent(transparent bool) {
if transparent {
atomic.StoreInt32(&screenTransparent, 1)
} else {
atomic.StoreInt32(&screenTransparent, 0)
}
screenTransparent.Store(transparent)
}
var screenTransparent int32 = 0
var screenTransparent atomic.Bool
// SetInitFocused sets whether the application is focused on show.
// 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.
func SetInitFocused(focused bool) {
if focused {
atomic.StoreInt32(&initUnfocused, 0)
} else {
atomic.StoreInt32(&initUnfocused, 1)
}
initUnfocused.Store(!focused)
}
var initUnfocused int32 = 0
var initUnfocused atomic.Bool
func toUIRunOptions(options *RunGameOptions) *ui.RunOptions {
const (
@ -690,8 +678,8 @@ func toUIRunOptions(options *RunGameOptions) *ui.RunOptions {
if options == nil {
return &ui.RunOptions{
InitUnfocused: atomic.LoadInt32(&initUnfocused) != 0,
ScreenTransparent: atomic.LoadInt32(&screenTransparent) != 0,
InitUnfocused: initUnfocused.Load(),
ScreenTransparent: screenTransparent.Load(),
X11ClassName: defaultX11ClassName,
X11InstanceName: defaultX11InstanceName,
}

View File

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