Skip to content

Commit

Permalink
mainloop: add optional C implementation
Browse files Browse the repository at this point in the history
This uses a specific build tag so as not to be on by default.
  • Loading branch information
zx2c4 committed May 24, 2019
1 parent 799a307 commit bb1f0be
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 28 deletions.
9 changes: 9 additions & 0 deletions README.mdown
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,12 @@ somewhere in your program. If you don't have `gcc` installed and on your `PATH`,
you can alternatively add `-linkmode internal` to the `-ldflags` of your `go build` command like so:

go build -ldflags="-H windowsgui -linkmode internal"

CGo Optimizations
=================

The usual default message loop includes calls to win32 API functions, which incurs a decent amount
of runtime overhead coming from Go. As an alternative to this, you may compile Walk using an
optional C implementation of the main message loop, by passing the `walk_use_cgo` build tag:

go build -tags walk_use_cgo
29 changes: 1 addition & 28 deletions form.go
Original file line number Diff line number Diff line change
Expand Up @@ -392,34 +392,7 @@ func (fb *FormBase) Run() int {

fb.SetBoundsPixels(fb.BoundsPixels())

msg := (*win.MSG)(unsafe.Pointer(win.GlobalAlloc(0, unsafe.Sizeof(win.MSG{}))))
defer win.GlobalFree(win.HGLOBAL(unsafe.Pointer(msg)))

for fb.hWnd != 0 {
switch win.GetMessage(msg, 0, 0, 0) {
case 0:
return int(msg.WParam)

case -1:
return -1
}

switch msg.Message {
case win.WM_KEYDOWN:
if fb.handleKeyDown(msg) {
continue
}
}

if !win.IsDialogMessage(fb.hWnd, msg) {
win.TranslateMessage(msg)
win.DispatchMessage(msg)
}

runSynchronized()
}

return 0
return fb.mainLoop()
}

func (fb *FormBase) handleKeyDown(msg *win.MSG) bool {
Expand Down
56 changes: 56 additions & 0 deletions mainloop_cgo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright 2019 The Walk Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build windows,walk_use_cgo

package walk

import (
"unsafe"

"github.com/lxn/win"
)

// #include <windows.h>
//
// extern void shimRunSynchronized(void);
// extern unsigned char shimHandleKeyDown(uintptr_t fb, uintptr_t m);
//
// static int mainloop(uintptr_t handle_ptr, uintptr_t fb_ptr)
// {
// HANDLE *hwnd = (HANDLE *)handle_ptr;
// MSG m;
// int r;
//
// while (*hwnd) {
// r = GetMessage(&m, NULL, 0, 0);
// if (!r)
// return m.wParam;
// else if (r < 0)
// return -1;
// if (m.message == WM_KEYDOWN && shimHandleKeyDown(fb_ptr, (uintptr_t)&m))
// continue;
// if (!IsDialogMessage(*hwnd, &m)) {
// TranslateMessage(&m);
// DispatchMessage(&m);
// }
// shimRunSynchronized();
// }
// return 0;
// }
import "C"

//export shimHandleKeyDown
func shimHandleKeyDown(fb uintptr, msg uintptr) bool {
return (*FormBase)(unsafe.Pointer(fb)).handleKeyDown((*win.MSG)(unsafe.Pointer(msg)))
}

//export shimRunSynchronized
func shimRunSynchronized() {
runSynchronized()
}

func (fb *FormBase) mainLoop() int {
return int(C.mainloop(C.uintptr_t(uintptr(unsafe.Pointer(&fb.hWnd))), C.uintptr_t(uintptr(unsafe.Pointer(fb)))))
}
43 changes: 43 additions & 0 deletions mainloop_default.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright 2019 The Walk Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build windows,!walk_use_cgo

package walk

import (
"github.com/lxn/win"
"unsafe"
)

func (fb *FormBase) mainLoop() int {
msg := (*win.MSG)(unsafe.Pointer(win.GlobalAlloc(0, unsafe.Sizeof(win.MSG{}))))
defer win.GlobalFree(win.HGLOBAL(unsafe.Pointer(msg)))

for fb.hWnd != 0 {
switch win.GetMessage(msg, 0, 0, 0) {
case 0:
return int(msg.WParam)

case -1:
return -1
}

switch msg.Message {
case win.WM_KEYDOWN:
if fb.handleKeyDown(msg) {
continue
}
}

if !win.IsDialogMessage(fb.hWnd, msg) {
win.TranslateMessage(msg)
win.DispatchMessage(msg)
}

runSynchronized()
}

return 0
}

0 comments on commit bb1f0be

Please sign in to comment.