Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 1 | # Introduction |
| 2 | |
elagergren-spideroak | bc43457 | 2018-09-06 16:03:56 -0700 | [diff] [blame] | 3 | Some libraries—especially graphical frameworks and libraries like Cocoa, OpenGL, and libSDL—use thread-local state and can require functions to be called only from a specific OS thread, typically the 'main' thread. Go provides the `runtime.LockOSThread` function for this, but it's notoriously difficult to use correctly. |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 4 | |
| 5 | # Solutions |
| 6 | |
| 7 | Russ Cox presented a good solution for this problem in this [thread](https://groups.google.com/d/msg/golang-nuts/IiWZ2hUuLDA/SNKYYZBelsYJ). |
| 8 | |
Dmitri Shuralyov | 47f767a | 2015-01-04 21:07:59 -0800 | [diff] [blame] | 9 | ```Go |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 10 | package sdl |
| 11 | |
| 12 | // Arrange that main.main runs on main thread. |
| 13 | func init() { |
Dave Day | 0d6986a | 2014-12-10 15:02:18 +1100 | [diff] [blame] | 14 | runtime.LockOSThread() |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 15 | } |
| 16 | |
| 17 | // Main runs the main SDL service loop. |
| 18 | // The binary's main.main must call sdl.Main() to run this loop. |
| 19 | // Main does not return. If the binary needs to do other work, it |
| 20 | // must do it in separate goroutines. |
| 21 | func Main() { |
Jeremy Jackins | 1804902 | 2015-01-27 22:24:43 +0900 | [diff] [blame] | 22 | for f := range mainfunc { |
Dave Day | 0d6986a | 2014-12-10 15:02:18 +1100 | [diff] [blame] | 23 | f() |
| 24 | } |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 25 | } |
| 26 | |
| 27 | // queue of work to run in main thread. |
| 28 | var mainfunc = make(chan func()) |
| 29 | |
| 30 | // do runs f on the main thread. |
| 31 | func do(f func()) { |
Dave Day | 0d6986a | 2014-12-10 15:02:18 +1100 | [diff] [blame] | 32 | done := make(chan bool, 1) |
| 33 | mainfunc <- func() { |
| 34 | f() |
| 35 | done <- true |
| 36 | } |
| 37 | <-done |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 38 | } |
| 39 | ``` |
| 40 | |
| 41 | And then other functions you write in package sdl can be like |
Dmitri Shuralyov | 47f767a | 2015-01-04 21:07:59 -0800 | [diff] [blame] | 42 | |
| 43 | ```Go |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 44 | func Beep() { |
Dave Day | 0d6986a | 2014-12-10 15:02:18 +1100 | [diff] [blame] | 45 | do(func() { |
| 46 | // whatever must run in main thread |
| 47 | }) |
Andrew Gerrand | 5bc444d | 2014-12-10 11:35:11 +1100 | [diff] [blame] | 48 | } |
| 49 | ``` |