Skip to content

Commit

Permalink
Add start/stop frontend lock
Browse files Browse the repository at this point in the history
  • Loading branch information
sergystepanov committed Oct 20, 2023
1 parent 38dc69e commit 10c4cd9
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 27 deletions.
48 changes: 24 additions & 24 deletions pkg/worker/caged/libretro/frontend.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ type Frontend struct {
th int // draw threads
vw, vh int // out frame size

mu sync.Mutex
mu sync.Mutex
mui sync.Mutex

DisableCanvasPool bool
SaveOnClose bool
Expand Down Expand Up @@ -198,7 +199,7 @@ func (f *Frontend) Shutdown() {
f.SetAudioCb(noAudio)
f.SetVideoCb(noVideo)
f.mu.Unlock()
f.log.Debug().Msgf("frontend closed")
f.log.Debug().Msgf("frontend shutdown done")
}

func (f *Frontend) linkNano(nano *nanoarch.Nanoarch) {
Expand All @@ -214,11 +215,14 @@ func (f *Frontend) linkNano(nano *nanoarch.Nanoarch) {
func (f *Frontend) SetOnAV(fn func()) { f.nano.OnSystemAvInfo = fn }

func (f *Frontend) Start() {
f.log.Debug().Msgf("Frontend start")
f.log.Debug().Msgf("frontend start")

f.done = make(chan struct{})
f.nano.LastFrameTime = time.Now().UnixNano()

f.mui.Lock()
defer f.Shutdown()
defer f.mui.Unlock()

if f.HasSave() {
// advance 1 frame for Mupen save state
Expand Down Expand Up @@ -248,34 +252,28 @@ func (f *Frontend) Start() {
}
}

func (f *Frontend) PixFormat() uint32 { return f.nano.Video.PixFmt.C }
func (f *Frontend) Rotation() uint { return f.nano.Rot }
func (f *Frontend) AudioSampleRate() int { return f.nano.AudioSampleRate() }
func (f *Frontend) FPS() int { return f.nano.VideoFramerate() }
func (f *Frontend) Flipped() bool { return f.nano.IsGL() }
func (f *Frontend) FrameSize() (int, int) { return f.nano.GeometryBase() }
func (f *Frontend) FPS() int { return f.nano.VideoFramerate() }
func (f *Frontend) HashPath() string { return f.storage.GetSavePath() }
func (f *Frontend) HasSave() bool { return os.Exists(f.HashPath()) }
func (f *Frontend) SRAMPath() string { return f.storage.GetSRAMPath() }
func (f *Frontend) AudioSampleRate() int { return f.nano.AudioSampleRate() }
func (f *Frontend) HashPath() string { return f.storage.GetSavePath() }
func (f *Frontend) Input(player int, data []byte) { f.input.setInput(player, data) }
func (f *Frontend) IsPortrait() bool { return f.nano.IsPortrait() }
func (f *Frontend) LoadGame(path string) error { return f.nano.LoadGame(path) }
func (f *Frontend) PixFormat() uint32 { return f.nano.Video.PixFmt.C }
func (f *Frontend) RestoreGameState() error { return f.Load() }
func (f *Frontend) Scale() float64 { return f.scale }
func (f *Frontend) IsPortrait() bool { return f.nano.IsPortrait() }
func (f *Frontend) Rotation() uint { return f.nano.Rot }
func (f *Frontend) SRAMPath() string { return f.storage.GetSRAMPath() }
func (f *Frontend) SaveGameState() error { return f.Save() }
func (f *Frontend) Scale() float64 { return f.scale }
func (f *Frontend) SetAudioCb(cb func(app.Audio)) { f.onAudio = cb }
func (f *Frontend) SetSessionId(name string) { f.storage.SetMainSaveName(name) }
func (f *Frontend) SetVideoCb(ff func(app.Video)) { f.onVideo = ff }
func (f *Frontend) SetViewport(width int, height int) {
f.mu.Lock()
f.vw, f.vh = width, height
f.mu.Unlock()
}

// Tick runs one emulation frame.
func (f *Frontend) Tick() { f.mu.Lock(); f.nano.Run(); f.mu.Unlock() }
func (f *Frontend) ToggleMultitap() { f.nano.ToggleMultitap() }
func (f *Frontend) ViewportSize() (int, int) { return f.vw, f.vh }
func (f *Frontend) SetViewport(w, h int) { f.mu.Lock(); f.vw, f.vh = w, h; f.mu.Unlock() }
func (f *Frontend) Tick() { f.mu.Lock(); f.nano.Run(); f.mu.Unlock() }
func (f *Frontend) ToggleMultitap() { f.nano.ToggleMultitap() }
func (f *Frontend) ViewportSize() (int, int) { return f.vw, f.vh }

func (f *Frontend) ViewportCalc() (nw int, nh int) {
w, h := f.FrameSize()
Expand Down Expand Up @@ -307,18 +305,20 @@ func (f *Frontend) ViewportCalc() (nw int, nh int) {
}

func (f *Frontend) Close() {
f.log.Debug().Msgf("frontend close called")
f.log.Debug().Msgf("frontend close")
close(f.done)

f.mui.Lock()
defer f.mui.Unlock()
// Save game on quit if it was saved before (shared or click-saved).
if f.SaveOnClose && f.HasSave() {
f.log.Debug().Msg("Save on quit")
if err := f.Save(); err != nil {
f.log.Error().Err(err).Msg("save on quit failed")
}
}

close(f.done)
f.nano.Close()
f.log.Debug().Msgf("frontend closed")
}

// Save writes the current state to the filesystem.
Expand Down
17 changes: 15 additions & 2 deletions pkg/worker/caged/libretro/frontend_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"path/filepath"
"sync"
"testing"
"time"

"github.com/giongto35/cloud-game/v3/pkg/config"
"github.com/giongto35/cloud-game/v3/pkg/logger"
Expand Down Expand Up @@ -67,9 +68,9 @@ func EmulatorMock(room string, system string) *TestFrontend {
conf.Emulator.Storage = expand("tests", "storage")

l := logger.Default()
l2 := l.Extend(l.Level(logger.ErrorLevel).With())
l2 := l.Extend(l.Level(logger.WarnLevel).With())

if err := manager.CheckCores(conf.Emulator, l); err != nil {
if err := manager.CheckCores(conf.Emulator, l2); err != nil {
panic(err)
}

Expand Down Expand Up @@ -354,6 +355,18 @@ func TestConcurrentInput(t *testing.T) {
wg.Wait()
}

func TestStartStop(t *testing.T) {
f1 := DefaultFrontend("sushi", sushi.system, sushi.rom)
go f1.Start()
time.Sleep(1 * time.Second)
f1.Close()

f2 := DefaultFrontend("sushi", sushi.system, sushi.rom)
go f2.Start()
time.Sleep(100 * time.Millisecond)
f2.Close()
}

// expand joins a list of file path elements.
func expand(p ...string) string {
ph, _ := filepath.Abs(filepath.FromSlash(filepath.Join(p...)))
Expand Down
2 changes: 1 addition & 1 deletion pkg/worker/coordinatorhandlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ func (c *coordinator) HandleGameStart(rq api.StartGameRequest[com.Uid], w *Worke
r = room.NewRoom[*room.GameSession](uid, nil, w.router.Users(), nil)
r.HandleClose = func() {
c.CloseRoom(uid)
c.log.Debug().Msgf("room close request %v sent")
c.log.Debug().Msgf("room close request %v sent", uid)
}

if other := w.router.Room(); other != nil {
Expand Down

0 comments on commit 10c4cd9

Please sign in to comment.