mainthread.go 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. package mainthread
  2. import (
  3. "errors"
  4. "runtime"
  5. )
  6. // CallQueueCap is the capacity of the call queue. This means how many calls to CallNonBlock will not
  7. // block until some call finishes.
  8. //
  9. // The default value is 16 and should be good for 99% usecases.
  10. var CallQueueCap = 16
  11. var (
  12. callQueue chan func()
  13. )
  14. func init() {
  15. runtime.LockOSThread()
  16. }
  17. func checkRun() {
  18. if callQueue == nil {
  19. panic(errors.New("mainthread: did not call Run"))
  20. }
  21. }
  22. // Run enables mainthread package functionality. To use mainthread package, put your main function
  23. // code into the run function (the argument to Run) and simply call Run from the real main function.
  24. //
  25. // Run returns when run (argument) function finishes.
  26. func Run(run func()) {
  27. callQueue = make(chan func(), CallQueueCap)
  28. done := make(chan struct{})
  29. go func() {
  30. run()
  31. done <- struct{}{}
  32. }()
  33. for {
  34. select {
  35. case f := <-callQueue:
  36. f()
  37. case <-done:
  38. return
  39. }
  40. }
  41. }
  42. // CallNonBlock queues function f on the main thread and returns immediately. Does not wait until f
  43. // finishes.
  44. func CallNonBlock(f func()) {
  45. checkRun()
  46. callQueue <- f
  47. }
  48. // Call queues function f on the main thread and blocks until the function f finishes.
  49. func Call(f func()) {
  50. checkRun()
  51. done := make(chan struct{})
  52. callQueue <- func() {
  53. f()
  54. done <- struct{}{}
  55. }
  56. <-done
  57. }
  58. // CallErr queues function f on the main thread and returns an error returned by f.
  59. func CallErr(f func() error) error {
  60. checkRun()
  61. errChan := make(chan error)
  62. callQueue <- func() {
  63. errChan <- f()
  64. }
  65. return <-errChan
  66. }
  67. // CallVal queues function f on the main thread and returns a value returned by f.
  68. func CallVal(f func() interface{}) interface{} {
  69. checkRun()
  70. respChan := make(chan interface{})
  71. callQueue <- func() {
  72. respChan <- f()
  73. }
  74. return <-respChan
  75. }