Skip to content

Commit

Permalink
content: multi-window demonstration
Browse files Browse the repository at this point in the history
  • Loading branch information
changkun committed Jan 23, 2021
1 parent 5276776 commit f1b5769
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 31 deletions.
73 changes: 47 additions & 26 deletions content/assets/zero-alloc-call-sched/app/window.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,59 +7,80 @@ package app

import (
"x/mainthread"
"x/thread"

"github.com/go-gl/glfw/v3.3/glfw"
)

// Init initializes an app environment.
func Init() (err error) {
mainthread.Call(func() { err = glfw.Init() })
return
}

// Terminate terminates the entire application.
func Terminate() {
mainthread.Call(glfw.Terminate)
}

// Win is a window.
type Win struct {
win *glfw.Window
th *thread.Thread
}

// NewWindow constructs a new graphical window.
func NewWindow() (*Win, error) {
var (
w = &Win{}
w = &Win{th: thread.New()}
err error
)
mainthread.Call(func() {
err = glfw.Init()
w.win, err = glfw.CreateWindow(640, 480, "", nil, nil)
if err != nil {
return
}

w.win, err = glfw.CreateWindow(640, 480, "win", nil, nil)
if err != nil {
return
}
w.win.MakeContextCurrent()
})

// This function can be called from any thread.
w.th.Call(w.win.MakeContextCurrent)
return w, nil
}

// Terminate terminates the entire application.
func Terminate() {
mainthread.Call(func() {
glfw.Terminate()
})
// Run runs the given window and blocks until it is destroied.
func (w *Win) Run() {
for !w.closed() {
w.update()
}
w.destroy()
}

// Closed asserts if the given window is closed.
// This function can be called from any thread.
func (w *Win) Closed() (stop bool) {
return w.win.ShouldClose()
// Stop stops the given window.
func (w *Win) Stop() {
// This function can be called from any threads.
w.th.Call(func() { w.win.SetShouldClose(true) })
}

// closed asserts if the given window is closed.
func (w *Win) closed() bool {
// This function can be called from any thread.
var stop bool
w.th.Call(func() { stop = w.win.ShouldClose() })
return stop
}

// Update updates the frame buffer of the given window.
// This function can be called from any thread.
func (w *Win) Update() {
w.win.SwapBuffers()
// glfw.WaitEventsTimeout(1.0 / 30)
glfw.PollEvents()
func (w *Win) update() {
mainthread.Call(func() {
w.win.SwapBuffers()
// This function must be called from the main thread.
glfw.WaitEventsTimeout(1.0 / 30)
})
}

// Stop stops the given window.
// This function can be called from any thread.
func (w *Win) Stop() {
w.win.SetShouldClose(true)
// destroy destructs the given window.
func (w *Win) destroy() {
// This function must be called from the mainthread.
mainthread.Call(w.win.Destroy)
w.th.Terminate()
}
32 changes: 27 additions & 5 deletions content/assets/zero-alloc-call-sched/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,21 +41,43 @@ options:
os.Exit(2)
}

w, err := app.NewWindow()
err = app.Init()
if err != nil {
panic(err)
}
defer app.Terminate()

w1, err := app.NewWindow()
if err != nil {
panic(err)
}
w2, err := app.NewWindow()
if err != nil {
panic(err)
}

done := make(chan struct{}, 3)
go func() {
defer func() { done <- struct{}{} }()
f, _ := os.Create(*traceF)
defer f.Close()
trace.Start(f)
defer trace.Stop()
time.Sleep(d)
w.Stop()
w1.Stop()
time.Sleep(d)
w2.Stop()
}()
for !w.Closed() {
w.Update()
}

go func() {
w1.Run()
done <- struct{}{}
}()
go func() {
w2.Run()
done <- struct{}{}
}()
<-done
<-done
<-done
}

0 comments on commit f1b5769

Please sign in to comment.