Skip to content

Commit

Permalink
Usb2Snes: fix race between data and connection update
Browse files Browse the repository at this point in the history
  • Loading branch information
black-sliver committed Jul 29, 2024
1 parent eb92d9c commit ce24865
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 7 deletions.
14 changes: 12 additions & 2 deletions src/core/autotracker.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,12 +215,19 @@ class AutoTracker final : public LuaInterface<AutoTracker>{
_snes->connect();
else
_snes->connect(_snesAddresses);
if (_snes->dostuff()) {

USB2SNES::Change changed = _snes->poll();
if (!!changed) {
int index = _backendIndex[_snes];
State oldState = _state[index];
bool wsConnected = _snes->wsConnected();
bool snesConnected = wsConnected ? _snes->snesConnected() : false;

if (!snesConnected && !!(changed & USB2SNES::Change::DATA)) {
// fire data change before firing disconnect
onDataChange.emit(this);
}

if (snesConnected) {
_state[index] = State::ConsoleConnected;
} else if (wsConnected) {
Expand All @@ -231,7 +238,10 @@ class AutoTracker final : public LuaInterface<AutoTracker>{

if (_state[index] != oldState) {
onStateChange.emit(this, index, _state[index]);
} else if (_state[index] == State::ConsoleConnected) {
}

if (snesConnected && !!(changed & USB2SNES::Change::DATA)) {
// fire data change after firing connect
onDataChange.emit(this);
}

Expand Down
11 changes: 7 additions & 4 deletions src/usb2snes/usb2snes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -448,17 +448,20 @@ bool USB2SNES::disconnect()
std::this_thread::sleep_for(std::chrono::milliseconds(1));
return true;
}
bool USB2SNES::dostuff()

USB2SNES::Change USB2SNES::poll()
{
bool res = false;
USB2SNES::Change res = USB2SNES::Change::NONE;
{
std::lock_guard<std::mutex> datalock(datamutex);
res |= data_changed;
if (data_changed)
res |= Change::DATA;
data_changed = false;
}
{
std::lock_guard<std::mutex> statelock(statemutex);
res |= state_changed;
if (state_changed)
res |= Change::STATE;
state_changed = false;
}
return res;
Expand Down
35 changes: 34 additions & 1 deletion src/usb2snes/usb2snes.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <chrono>
#include <vector>
#include <string>
#include <type_traits>

class USB2SNES {
public:
Expand All @@ -20,11 +21,17 @@ class USB2SNES {
SA1,
};

enum class Change : unsigned {
NONE = 0,
STATE = 1,
DATA = 2,
};

USB2SNES(const std::string& appname);
~USB2SNES();
bool connect(std::vector<std::string> uris = {QUSB2SNES_URI,LEGACY_URI});
bool disconnect();
bool dostuff();
Change poll();
static constexpr auto QUSB2SNES_URI = "ws://localhost:23074";
static constexpr auto LEGACY_URI = "ws://localhost:8080";
bool wsConnected();
Expand Down Expand Up @@ -159,5 +166,31 @@ T USB2SNES::readInt(uint32_t addr)
return res;
}

static inline USB2SNES::Change operator|(USB2SNES::Change lhs, USB2SNES::Change rhs)
{
return static_cast<USB2SNES::Change>(
static_cast<typename std::underlying_type<USB2SNES::Change>::type>(lhs) |
static_cast<typename std::underlying_type<USB2SNES::Change>::type>(rhs)
);
}

static inline USB2SNES::Change& operator|=(USB2SNES::Change& lhs, USB2SNES::Change rhs)
{
return lhs = lhs | rhs;
}

static inline USB2SNES::Change operator&(USB2SNES::Change lhs, USB2SNES::Change rhs)
{
return static_cast<USB2SNES::Change>(
static_cast<typename std::underlying_type<USB2SNES::Change>::type>(lhs) &
static_cast<typename std::underlying_type<USB2SNES::Change>::type>(rhs)
);
}

static inline bool operator!(USB2SNES::Change e) {
return e == static_cast<USB2SNES::Change>(0);
}


#endif // _USB2SNES_H_INCLUDED

0 comments on commit ce24865

Please sign in to comment.