From 6588872e4254b3ab67ba9cb9537aab4fb291848a Mon Sep 17 00:00:00 2001 From: Sour Date: Sun, 3 Dec 2017 23:12:16 -0500 Subject: [PATCH] Input: Fixed crash due to multithreading issues w/ controller state access --- Core/BarcodeBattlerReader.h | 3 ++- Core/BaseControlDevice.cpp | 12 ++++++++++++ Core/BaseControlDevice.h | 6 +++++- Core/FamilyBasicDataRecorder.h | 2 +- 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/Core/BarcodeBattlerReader.h b/Core/BarcodeBattlerReader.h index 789ee9e7..b1b0736d 100644 --- a/Core/BarcodeBattlerReader.h +++ b/Core/BarcodeBattlerReader.h @@ -30,7 +30,8 @@ protected: void InitBarcodeStream() { - string barcodeText(_state.State.begin(), _state.State.end()); + vector state = GetRawState().State; + string barcodeText(state.begin(), state.end()); //Signature at the end, needed for code to be recognized barcodeText += "EPOCH\xD\xA"; diff --git a/Core/BaseControlDevice.cpp b/Core/BaseControlDevice.cpp index 361c6021..a8fe4eca 100644 --- a/Core/BaseControlDevice.cpp +++ b/Core/BaseControlDevice.cpp @@ -31,6 +31,7 @@ void BaseControlDevice::InternalSetStateFromInput() void BaseControlDevice::StreamState(bool saving) { + auto lock = _stateLock.AcquireSafe(); VectorInfo state{ &_state.State }; Stream(_strobe, state); } @@ -64,21 +65,25 @@ void BaseControlDevice::StrobeProcessWrite(uint8_t value) void BaseControlDevice::ClearState() { + auto lock = _stateLock.AcquireSafe(); _state = ControlDeviceState(); } ControlDeviceState BaseControlDevice::GetRawState() { + auto lock = _stateLock.AcquireSafe(); return _state; } void BaseControlDevice::SetRawState(ControlDeviceState state) { + auto lock = _stateLock.AcquireSafe(); _state = state; } void BaseControlDevice::SetTextState(string textState) { + auto lock = _stateLock.AcquireSafe(); ClearState(); if(IsRawString()) { @@ -112,6 +117,7 @@ void BaseControlDevice::SetTextState(string textState) string BaseControlDevice::GetTextState() { + auto lock = _stateLock.AcquireSafe(); if(IsRawString()) { return string((char*)_state.State.data(), _state.State.size()); } else { @@ -133,6 +139,7 @@ string BaseControlDevice::GetTextState() void BaseControlDevice::EnsureCapacity(int32_t minBitCount) { + auto lock = _stateLock.AcquireSafe(); uint32_t minByteCount = minBitCount / 8 + 1 + (HasCoordinates() ? 32 : 0); int32_t gap = minByteCount - (int32_t)_state.State.size(); @@ -158,6 +165,7 @@ uint32_t BaseControlDevice::GetByteIndex(uint8_t bit) bool BaseControlDevice::IsPressed(uint8_t bit) { + auto lock = _stateLock.AcquireSafe(); EnsureCapacity(bit); uint8_t bitMask = 1 << (bit % 8); return (_state.State[GetByteIndex(bit)] & bitMask) != 0; @@ -174,6 +182,7 @@ void BaseControlDevice::SetBitValue(uint8_t bit, bool set) void BaseControlDevice::SetBit(uint8_t bit) { + auto lock = _stateLock.AcquireSafe(); EnsureCapacity(bit); uint8_t bitMask = 1 << (bit % 8); _state.State[GetByteIndex(bit)] |= bitMask; @@ -181,6 +190,7 @@ void BaseControlDevice::SetBit(uint8_t bit) void BaseControlDevice::ClearBit(uint8_t bit) { + auto lock = _stateLock.AcquireSafe(); EnsureCapacity(bit); uint8_t bitMask = 1 << (bit % 8); _state.State[GetByteIndex(bit)] &= ~bitMask; @@ -211,6 +221,7 @@ void BaseControlDevice::SetPressedState(uint8_t bit, bool enabled) void BaseControlDevice::SetCoordinates(MousePosition pos) { + auto lock = _stateLock.AcquireSafe(); EnsureCapacity(-1); _state.State[0] = pos.X & 0xFF; @@ -221,6 +232,7 @@ void BaseControlDevice::SetCoordinates(MousePosition pos) MousePosition BaseControlDevice::GetCoordinates() { + auto lock = _stateLock.AcquireSafe(); EnsureCapacity(-1); MousePosition pos; diff --git a/Core/BaseControlDevice.h b/Core/BaseControlDevice.h index 42caa60f..72f5e962 100644 --- a/Core/BaseControlDevice.h +++ b/Core/BaseControlDevice.h @@ -4,14 +4,18 @@ #include "Snapshotable.h" #include "ControlManager.h" #include "ControlDeviceState.h" +#include "../Utilities/SimpleLock.h" class BaseControlDevice : public Snapshotable { -protected: +private: ControlDeviceState _state; + +protected: vector _keyMappings; bool _strobe; uint8_t _port; + SimpleLock _stateLock; virtual void RefreshStateBuffer() { } virtual void StreamState(bool saving); diff --git a/Core/FamilyBasicDataRecorder.h b/Core/FamilyBasicDataRecorder.h index 23d17863..c1a7508b 100644 --- a/Core/FamilyBasicDataRecorder.h +++ b/Core/FamilyBasicDataRecorder.h @@ -57,7 +57,7 @@ public: void OnAfterSetState() override { - if(_state.State.size() > 0) { + if(GetRawState().State.size() > 0) { _data = Base64::Decode(GetTextState()); _cycle = CPU::GetCycleCount(); _isPlaying = true;