sciter-sdk / go-sciter

Golang bindings of Sciter: the Embeddable HTML/CSS/script engine for modern UI development
https://sciter.com
2.57k stars 269 forks source link

Is calling sciter functions from another goroutine safe? #133

Open dodobyte opened 6 years ago

dodobyte commented 6 years ago

I call tiscript functions from a seperate goroutine, not the gui one. Is this allright? If not how can i call them in gui thread. After w.Run() i lost control of the gui.

If there's a mechanism to run code in gui thread like a callback or message handler, i would appreciate any information about it.

Also should i lock gui OS thread with runtime.LockOSThread()?

pravic commented 6 years ago
  1. You can call UI (by UI I mean DOM elements and their methods in HTML) from any thread, almost all API functions are thread safe. In fact, they will be executed in GUI thread automatically.

  2. You can also store script functions in sciter.Value and call them later from goroutines or OS threads.

As for the LockOSThread - I think, you don't have to call it.

dodobyte commented 6 years ago

Great, Thank you.

pravic commented 6 years ago

If there's a mechanism to run code in gui thread like a callback or message handler, i would appreciate any information about it.

Could you describe your case? When do you want to create a new window? Usually it is done either in the beginning (main window) or in reaction of some event (e.g button click).

dodobyte commented 6 years ago

Could you describe your case?

I have a job that takes long time (would hang the gui) so i run it in another goroutine and update GUI from that goroutine. In windows you cannot update GUI from another thread, you may pass a message to GUI message queue so the update is done by the GUI thread. Every GUI library i've worked with had this limitation since the GUI is a shared resource.

If sciter queues GUI calls to run on GUI thread implicitly, there should not be a problem for my case.

I believe the cause of the panic is related to my second question (about runtime.LockOSThread()).

Since Go has it's own scheduler for goroutines, it switches the goroutine which created the GUI to another OS thread anytime it wants.

This causes trouble for almost every graphics related libraries. The solution is to lock GUI goroutine to underlying OS thread. Thus the GUI related codes will always run on the same OS thread.

So i believe runtime.LockOSThread() is necessary and should solve the problem.

references: https://golang.org/pkg/runtime/#LockOSThread https://github.com/golang/go/wiki/LockOSThread

edit: You were right about sciter queuing GUI calls to run on GUI thread. https://sciter.com/making-api-thread-safe/

The only problem left is go switching GUI goroutine to antoher OS thread, this init code guarantees that won't happen.

func init() {
    runtime.LockOSThread()
}

Of course the main goroutine should create the window.