app/internal/window: [Windows] avoid race between Main and window closes

While here, replace the window hwnd-to-window map with a sync.Map.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2020-06-08 11:39:40 +02:00
parent bda315e687
commit 64a516d7c9
+18 -25
View File
@@ -42,7 +42,9 @@ type window struct {
const _WM_REDRAW = windows.WM_USER + 0 const _WM_REDRAW = windows.WM_USER + 0
var mainDone = make(chan struct{}) // windowCounter keeps track of the number of windows.
// A send of +1 or -1 represents a change in window count.
var windowCounter = make(chan int)
type gpuAPI struct { type gpuAPI struct {
priority int priority int
@@ -53,10 +55,8 @@ type gpuAPI struct {
// implementations. // implementations.
var backends []gpuAPI var backends []gpuAPI
var winMap struct { // winMap maps win32 HWNDs to *windows.
mu sync.Mutex var winMap sync.Map
windows map[syscall.Handle]*window
}
var resources struct { var resources struct {
once sync.Once once sync.Once
@@ -68,12 +68,12 @@ var resources struct {
cursor syscall.Handle cursor syscall.Handle
} }
func init() {
winMap.windows = make(map[syscall.Handle]*window)
}
func Main() { func Main() {
<-mainDone // Wait for first window
count := <-windowCounter
for count > 0 {
count += <-windowCounter
}
} }
func NewWindow(window Callbacks, opts *Options) error { func NewWindow(window Callbacks, opts *Options) error {
@@ -88,19 +88,11 @@ func NewWindow(window Callbacks, opts *Options) error {
} }
defer w.destroy() defer w.destroy()
cerr <- nil cerr <- nil
winMap.mu.Lock() winMap.Store(w.hwnd, w)
winMap.windows[w.hwnd] = w windowCounter <- +1
winMap.mu.Unlock()
defer func() { defer func() {
winMap.mu.Lock() winMap.Delete(w.hwnd)
defer winMap.mu.Unlock() windowCounter <- -1
delete(winMap.windows, w.hwnd)
if len(winMap.windows) == 0 {
select {
case mainDone <- struct{}{}:
default:
}
}
}() }()
w.w = window w.w = window
w.w.SetDriver(w) w.w.SetDriver(w)
@@ -185,9 +177,10 @@ func createNativeWindow(opts *Options) (*window, error) {
} }
func windowProc(hwnd syscall.Handle, msg uint32, wParam, lParam uintptr) uintptr { func windowProc(hwnd syscall.Handle, msg uint32, wParam, lParam uintptr) uintptr {
winMap.mu.Lock() var w *window
w := winMap.windows[hwnd] if win, exists := winMap.Load(hwnd); exists {
winMap.mu.Unlock() w = win.(*window)
}
switch msg { switch msg {
case windows.WM_UNICHAR: case windows.WM_UNICHAR:
if wParam == windows.UNICODE_NOCHAR { if wParam == windows.UNICODE_NOCHAR {