uidriver/glfw: Reduce mutex to avoid potential deadlock

This commit is contained in:
Hajime Hoshi 2019-08-19 01:01:43 +09:00
parent 25ac788ee6
commit 4d0e23c460
2 changed files with 65 additions and 58 deletions

View File

@ -47,7 +47,6 @@ type Input struct {
touches map[int]pos // This is not updated until GLFW 3.3 is available (#417)
runeBuffer []rune
ui *UserInterface
m sync.RWMutex
}
type pos struct {
@ -56,14 +55,15 @@ type pos struct {
}
func (i *Input) CursorPosition() (x, y int) {
i.m.RLock()
defer i.m.RUnlock()
return i.ui.adjustPosition(i.cursorX, i.cursorY)
i.ui.m.RLock()
cx, cy := i.cursorX, i.cursorY
i.ui.m.RUnlock()
return i.ui.adjustPosition(cx, cy)
}
func (i *Input) GamepadIDs() []int {
i.m.RLock()
defer i.m.RUnlock()
i.ui.m.RLock()
defer i.ui.m.RUnlock()
if len(i.gamepads) == 0 {
return nil
}
@ -77,8 +77,8 @@ func (i *Input) GamepadIDs() []int {
}
func (i *Input) GamepadAxisNum(id int) int {
i.m.RLock()
defer i.m.RUnlock()
i.ui.m.RLock()
defer i.ui.m.RUnlock()
if len(i.gamepads) <= id {
return 0
}
@ -86,8 +86,8 @@ func (i *Input) GamepadAxisNum(id int) int {
}
func (i *Input) GamepadAxis(id int, axis int) float64 {
i.m.RLock()
defer i.m.RUnlock()
i.ui.m.RLock()
defer i.ui.m.RUnlock()
if len(i.gamepads) <= id {
return 0
}
@ -95,8 +95,8 @@ func (i *Input) GamepadAxis(id int, axis int) float64 {
}
func (i *Input) GamepadButtonNum(id int) int {
i.m.RLock()
defer i.m.RUnlock()
i.ui.m.RLock()
defer i.ui.m.RUnlock()
if len(i.gamepads) <= id {
return 0
}
@ -104,8 +104,8 @@ func (i *Input) GamepadButtonNum(id int) int {
}
func (i *Input) IsGamepadButtonPressed(id int, button driver.GamepadButton) bool {
i.m.RLock()
defer i.m.RUnlock()
i.ui.m.RLock()
defer i.ui.m.RUnlock()
if len(i.gamepads) <= id {
return false
}
@ -113,8 +113,8 @@ func (i *Input) IsGamepadButtonPressed(id int, button driver.GamepadButton) bool
}
func (i *Input) TouchIDs() []int {
i.m.RLock()
defer i.m.RUnlock()
i.ui.m.RLock()
defer i.ui.m.RUnlock()
if len(i.touches) == 0 {
return nil
@ -128,33 +128,40 @@ func (i *Input) TouchIDs() []int {
}
func (i *Input) TouchPosition(id int) (x, y int) {
i.m.RLock()
defer i.m.RUnlock()
i.ui.m.RLock()
found := false
var p pos
for tid, pos := range i.touches {
if id == tid {
return i.ui.adjustPosition(pos.X, pos.Y)
p = pos
found = true
break
}
}
i.ui.m.RUnlock()
if !found {
return 0, 0
}
return i.ui.adjustPosition(p.X, p.Y)
}
func (i *Input) RuneBuffer() []rune {
i.m.RLock()
defer i.m.RUnlock()
i.ui.m.RLock()
defer i.ui.m.RUnlock()
return i.runeBuffer
}
func (i *Input) ResetForFrame() {
i.m.RLock()
defer i.m.RUnlock()
i.ui.m.RLock()
defer i.ui.m.RUnlock()
i.runeBuffer = i.runeBuffer[:0]
i.scrollX, i.scrollY = 0, 0
}
func (i *Input) IsKeyPressed(key driver.Key) bool {
i.m.RLock()
defer i.m.RUnlock()
i.ui.m.RLock()
defer i.ui.m.RUnlock()
if i.keyPressed == nil {
i.keyPressed = map[glfw.Key]bool{}
}
@ -170,8 +177,8 @@ func (i *Input) IsKeyPressed(key driver.Key) bool {
}
func (i *Input) IsMouseButtonPressed(button driver.MouseButton) bool {
i.m.RLock()
defer i.m.RUnlock()
i.ui.m.RLock()
defer i.ui.m.RUnlock()
if i.mouseButtonPressed == nil {
i.mouseButtonPressed = map[glfw.MouseButton]bool{}
}
@ -187,8 +194,8 @@ func (i *Input) IsMouseButtonPressed(button driver.MouseButton) bool {
}
func (i *Input) Wheel() (xoff, yoff float64) {
i.m.RLock()
defer i.m.RUnlock()
i.ui.m.RLock()
defer i.ui.m.RUnlock()
return i.scrollX, i.scrollY
}
@ -202,21 +209,21 @@ func (i *Input) appendRuneBuffer(char rune) {
if !unicode.IsPrint(char) {
return
}
i.m.Lock()
i.ui.m.Lock()
i.runeBuffer = append(i.runeBuffer, char)
i.m.Unlock()
i.ui.m.Unlock()
}
func (i *Input) setWheel(xoff, yoff float64) {
i.m.Lock()
i.ui.m.Lock()
i.scrollX = xoff
i.scrollY = yoff
i.m.Unlock()
i.ui.m.Unlock()
}
func (i *Input) update(window *glfw.Window, scale float64) {
i.m.Lock()
defer i.m.Unlock()
i.ui.m.Lock()
defer i.ui.m.Unlock()
i.onceCallback.Do(func() {
window.SetCharModsCallback(func(w *glfw.Window, char rune, mods glfw.ModifierKey) {

View File

@ -68,7 +68,7 @@ type UserInterface struct {
input Input
t *thread.Thread
m sync.Mutex
m sync.RWMutex
}
const (
@ -178,9 +178,9 @@ func getCachedMonitor(wx, wy int) (*cachedMonitor, bool) {
}
func (u *UserInterface) isRunning() bool {
u.m.Lock()
u.m.RLock()
v := u.running
u.m.Unlock()
u.m.RUnlock()
return v
}
@ -191,9 +191,9 @@ func (u *UserInterface) setRunning(running bool) {
}
func (u *UserInterface) isInitFullscreen() bool {
u.m.Lock()
u.m.RLock()
v := u.initFullscreen
u.m.Unlock()
u.m.RUnlock()
return v
}
@ -204,9 +204,9 @@ func (u *UserInterface) setInitFullscreen(initFullscreen bool) {
}
func (u *UserInterface) isInitCursorVisible() bool {
u.m.Lock()
u.m.RLock()
v := u.initCursorVisible
u.m.Unlock()
u.m.RUnlock()
return v
}
@ -217,9 +217,9 @@ func (u *UserInterface) setInitCursorVisible(visible bool) {
}
func (u *UserInterface) isInitWindowDecorated() bool {
u.m.Lock()
u.m.RLock()
v := u.initWindowDecorated
u.m.Unlock()
u.m.RUnlock()
return v
}
@ -230,9 +230,9 @@ func (u *UserInterface) setInitWindowDecorated(decorated bool) {
}
func (u *UserInterface) isRunnableInBackground() bool {
u.m.Lock()
u.m.RLock()
v := u.runnableInBackground
u.m.Unlock()
u.m.RUnlock()
return v
}
@ -243,9 +243,9 @@ func (u *UserInterface) setRunnableInBackground(runnableInBackground bool) {
}
func (u *UserInterface) isInitWindowResizable() bool {
u.m.Lock()
u.m.RLock()
v := u.initWindowResizable
u.m.Unlock()
u.m.RUnlock()
return v
}
@ -256,9 +256,9 @@ func (u *UserInterface) setInitWindowResizable(resizable bool) {
}
func (u *UserInterface) getInitIconImages() []image.Image {
u.m.Lock()
u.m.RLock()
i := u.initIconImages
u.m.Unlock()
u.m.RUnlock()
return i
}
@ -362,9 +362,9 @@ func (u *UserInterface) SetVsyncEnabled(enabled bool) {
// m is not used for updating vsync in setScreenSize so far, but
// it should be OK since any goroutines can't reach here when
// the game already starts and setScreenSize can be called.
u.m.Lock()
u.m.RLock()
u.vsync = enabled
u.m.Unlock()
u.m.RUnlock()
return
}
_ = u.t.Call(func() error {
@ -374,9 +374,9 @@ func (u *UserInterface) SetVsyncEnabled(enabled bool) {
}
func (u *UserInterface) IsVsyncEnabled() bool {
u.m.Lock()
u.m.RLock()
r := u.vsync
u.m.Unlock()
u.m.RUnlock()
return r
}
@ -822,9 +822,9 @@ func (u *UserInterface) loop(context driver.UIContext) error {
return err
}
u.m.Lock()
u.m.RLock()
vsync := u.vsync
u.m.Unlock()
u.m.RUnlock()
_ = u.t.Call(func() error {
if !vsync {