fix excessive memory usage by m_ButtonState
This commit is contained in:
@@ -8,6 +8,22 @@
|
|||||||
#include "Foreach.h"
|
#include "Foreach.h"
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
|
struct ButtonState
|
||||||
|
{
|
||||||
|
ButtonState();
|
||||||
|
bool m_BeingHeld; // actual current state
|
||||||
|
bool m_bLastReportedHeld; // last state reported by Update()
|
||||||
|
CString m_sComment;
|
||||||
|
float m_fSecsHeld;
|
||||||
|
float m_Level, m_LastLevel;
|
||||||
|
|
||||||
|
// Timestamp of m_BeingHeld changing.
|
||||||
|
RageTimer m_BeingHeldTime;
|
||||||
|
|
||||||
|
// The time that we actually reported the last event (used for debouncing).
|
||||||
|
RageTimer m_LastReportTime;
|
||||||
|
};
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
/* Maintain a set of all interesting buttons: buttons which are being held
|
/* Maintain a set of all interesting buttons: buttons which are being held
|
||||||
@@ -15,11 +31,11 @@ namespace
|
|||||||
* optimize InputFilter::Update, so we don't have to process every button
|
* optimize InputFilter::Update, so we don't have to process every button
|
||||||
* we know about when most of them aren't in use. This set is protected
|
* we know about when most of them aren't in use. This set is protected
|
||||||
* by queuemutex. */
|
* by queuemutex. */
|
||||||
typedef pair<InputDevice,DeviceButton> Button;
|
typedef map<DeviceInput, ButtonState> ButtonStateMap;
|
||||||
set<Button> g_ButtonsToProcess;
|
ButtonStateMap g_ButtonStates;
|
||||||
void ActivateButton( const DeviceInput &di )
|
ButtonState &GetButtonState( InputDevice device, DeviceButton button )
|
||||||
{
|
{
|
||||||
g_ButtonsToProcess.insert( make_pair(di.device, di.button) );
|
return g_ButtonStates[ DeviceInput(device, button) ];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,6 +78,7 @@ InputFilter::InputFilter()
|
|||||||
InputFilter::~InputFilter()
|
InputFilter::~InputFilter()
|
||||||
{
|
{
|
||||||
delete queuemutex;
|
delete queuemutex;
|
||||||
|
g_ButtonStates.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputFilter::Reset()
|
void InputFilter::Reset()
|
||||||
@@ -82,7 +99,7 @@ void InputFilter::ResetRepeatRate()
|
|||||||
SetRepeatRate( TIME_BEFORE_SLOW_REPEATS, TIME_BEFORE_FAST_REPEATS, REPEATS_PER_SEC );
|
SetRepeatRate( TIME_BEFORE_SLOW_REPEATS, TIME_BEFORE_FAST_REPEATS, REPEATS_PER_SEC );
|
||||||
}
|
}
|
||||||
|
|
||||||
InputFilter::ButtonState::ButtonState():
|
ButtonState::ButtonState():
|
||||||
m_BeingHeldTime(RageZeroTimer),
|
m_BeingHeldTime(RageZeroTimer),
|
||||||
m_LastReportTime(RageZeroTimer)
|
m_LastReportTime(RageZeroTimer)
|
||||||
{
|
{
|
||||||
@@ -101,7 +118,7 @@ void InputFilter::ButtonPressed( const DeviceInput &di, bool Down )
|
|||||||
ASSERT_M( di.device < NUM_INPUT_DEVICES, ssprintf("%i", di.device) );
|
ASSERT_M( di.device < NUM_INPUT_DEVICES, ssprintf("%i", di.device) );
|
||||||
ASSERT_M( di.button < NUM_DeviceButton, ssprintf("%i", di.button) );
|
ASSERT_M( di.button < NUM_DeviceButton, ssprintf("%i", di.button) );
|
||||||
|
|
||||||
ButtonState &bs = m_ButtonState[di.device][di.button];
|
ButtonState &bs = GetButtonState( di.device, di.button );
|
||||||
|
|
||||||
bs.m_Level = di.level;
|
bs.m_Level = di.level;
|
||||||
|
|
||||||
@@ -117,14 +134,12 @@ void InputFilter::ButtonPressed( const DeviceInput &di, bool Down )
|
|||||||
/* Try to report presses immediately. */
|
/* Try to report presses immediately. */
|
||||||
CheckButtonChange( bs, di, now );
|
CheckButtonChange( bs, di, now );
|
||||||
}
|
}
|
||||||
|
|
||||||
ActivateButton( di );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputFilter::SetButtonComment( const DeviceInput &di, const CString &sComment )
|
void InputFilter::SetButtonComment( const DeviceInput &di, const CString &sComment )
|
||||||
{
|
{
|
||||||
LockMut(*queuemutex);
|
LockMut(*queuemutex);
|
||||||
ButtonState &bs = m_ButtonState[di.device][di.button];
|
ButtonState &bs = GetButtonState( di.device, di.button );
|
||||||
bs.m_sComment = sComment;
|
bs.m_sComment = sComment;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,11 +148,14 @@ void InputFilter::ResetDevice( InputDevice device )
|
|||||||
{
|
{
|
||||||
LockMut(*queuemutex);
|
LockMut(*queuemutex);
|
||||||
RageTimer now;
|
RageTimer now;
|
||||||
set<Button> Buttons( g_ButtonsToProcess );
|
|
||||||
FOREACHS( Button, Buttons, b )
|
vector<DeviceInput> DeviceInputs;
|
||||||
|
GetPressedButtons( DeviceInputs );
|
||||||
|
|
||||||
|
FOREACH( DeviceInput, DeviceInputs, di )
|
||||||
{
|
{
|
||||||
if( b->first == device )
|
if( di->device == device )
|
||||||
ButtonPressed( DeviceInput(device, b->second, -1, now), false );
|
ButtonPressed( DeviceInput(device, di->button, -1, now), false );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,12 +190,13 @@ void InputFilter::Update( float fDeltaTime )
|
|||||||
|
|
||||||
DeviceInput di( (InputDevice)0,DeviceButton_Invalid,1.0f,now);
|
DeviceInput di( (InputDevice)0,DeviceButton_Invalid,1.0f,now);
|
||||||
|
|
||||||
set<Button> Buttons( g_ButtonsToProcess );
|
vector<ButtonStateMap::iterator> ButtonsToErase;
|
||||||
FOREACHS( Button, Buttons, b )
|
|
||||||
|
FOREACHM( DeviceInput, ButtonState, g_ButtonStates, b )
|
||||||
{
|
{
|
||||||
di.device = b->first;
|
di.device = b->first.device;
|
||||||
di.button = b->second;
|
di.button = b->first.button;
|
||||||
ButtonState &bs = m_ButtonState[di.device][di.button];
|
ButtonState &bs = b->second;
|
||||||
di.level = bs.m_Level;
|
di.level = bs.m_Level;
|
||||||
|
|
||||||
/* Generate IET_FIRST_PRESS and IET_RELEASE events that were delayed. */
|
/* Generate IET_FIRST_PRESS and IET_RELEASE events that were delayed. */
|
||||||
@@ -193,7 +212,10 @@ void InputFilter::Update( float fDeltaTime )
|
|||||||
/* Generate IET_FAST_REPEAT and IET_SLOW_REPEAT events. */
|
/* Generate IET_FAST_REPEAT and IET_SLOW_REPEAT events. */
|
||||||
if( !bs.m_bLastReportedHeld )
|
if( !bs.m_bLastReportedHeld )
|
||||||
{
|
{
|
||||||
g_ButtonsToProcess.erase( make_pair(di.device, di.button) );
|
// If the key isn't pressed, and hasn't been pressed for a while (so debouncing
|
||||||
|
// isn't interested in it), purge the entry.
|
||||||
|
if( now - bs.m_LastReportTime > g_fInputDebounceTime )
|
||||||
|
ButtonsToErase.push_back( b );
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,27 +260,33 @@ void InputFilter::Update( float fDeltaTime )
|
|||||||
queue.push_back( InputEvent(di,iet) );
|
queue.push_back( InputEvent(di,iet) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FOREACH( ButtonStateMap::iterator, ButtonsToErase, it )
|
||||||
|
g_ButtonStates.erase( *it );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InputFilter::IsBeingPressed( const DeviceInput &di )
|
bool InputFilter::IsBeingPressed( const DeviceInput &di )
|
||||||
{
|
{
|
||||||
return m_ButtonState[di.device][di.button].m_bLastReportedHeld;
|
LockMut(*queuemutex);
|
||||||
|
return GetButtonState(di.device, di.button).m_bLastReportedHeld;
|
||||||
}
|
}
|
||||||
|
|
||||||
float InputFilter::GetSecsHeld( const DeviceInput &di )
|
float InputFilter::GetSecsHeld( const DeviceInput &di )
|
||||||
{
|
{
|
||||||
return m_ButtonState[di.device][di.button].m_fSecsHeld;
|
LockMut(*queuemutex);
|
||||||
|
return GetButtonState(di.device, di.button).m_fSecsHeld;
|
||||||
}
|
}
|
||||||
|
|
||||||
CString InputFilter::GetButtonComment( const DeviceInput &di ) const
|
CString InputFilter::GetButtonComment( const DeviceInput &di ) const
|
||||||
{
|
{
|
||||||
LockMut(*queuemutex);
|
LockMut(*queuemutex);
|
||||||
return m_ButtonState[di.device][di.button].m_sComment;
|
return GetButtonState(di.device, di.button).m_sComment;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputFilter::ResetKeyRepeat( const DeviceInput &di )
|
void InputFilter::ResetKeyRepeat( const DeviceInput &di )
|
||||||
{
|
{
|
||||||
m_ButtonState[di.device][di.button].m_fSecsHeld = 0;
|
LockMut(*queuemutex);
|
||||||
|
GetButtonState(di.device, di.button).m_fSecsHeld = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputFilter::GetInputEvents( InputEventArray &array )
|
void InputFilter::GetInputEvents( InputEventArray &array )
|
||||||
@@ -268,6 +296,20 @@ void InputFilter::GetInputEvents( InputEventArray &array )
|
|||||||
queue.clear();
|
queue.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InputFilter::GetPressedButtons( vector<DeviceInput> &array )
|
||||||
|
{
|
||||||
|
LockMut(*queuemutex);
|
||||||
|
FOREACHM( DeviceInput, ButtonState, g_ButtonStates, b )
|
||||||
|
{
|
||||||
|
if( b->second.m_BeingHeld )
|
||||||
|
{
|
||||||
|
DeviceInput di = b->first;
|
||||||
|
di.level = b->second.m_Level;
|
||||||
|
array.push_back( di );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (c) 2001-2004 Chris Danford
|
* (c) 2001-2004 Chris Danford
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ struct InputEvent : public DeviceInput
|
|||||||
typedef vector<InputEvent> InputEventArray;
|
typedef vector<InputEvent> InputEventArray;
|
||||||
|
|
||||||
class RageMutex;
|
class RageMutex;
|
||||||
|
struct ButtonState;
|
||||||
class InputFilter
|
class InputFilter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -59,24 +60,9 @@ public:
|
|||||||
CString GetButtonComment( const DeviceInput &di ) const;
|
CString GetButtonComment( const DeviceInput &di ) const;
|
||||||
|
|
||||||
void GetInputEvents( InputEventArray &array );
|
void GetInputEvents( InputEventArray &array );
|
||||||
|
void GetPressedButtons( vector<DeviceInput> &array );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct ButtonState
|
|
||||||
{
|
|
||||||
ButtonState();
|
|
||||||
bool m_BeingHeld; // actual current state
|
|
||||||
bool m_bLastReportedHeld; // last state reported by Update()
|
|
||||||
CString m_sComment;
|
|
||||||
float m_fSecsHeld;
|
|
||||||
float m_Level, m_LastLevel;
|
|
||||||
|
|
||||||
// Timestamp of m_BeingHeld changing.
|
|
||||||
RageTimer m_BeingHeldTime;
|
|
||||||
|
|
||||||
// The time that we actually reported the last event (used for debouncing).
|
|
||||||
RageTimer m_LastReportTime;
|
|
||||||
};
|
|
||||||
ButtonState m_ButtonState[NUM_INPUT_DEVICES][NUM_DeviceButton];
|
|
||||||
void CheckButtonChange( ButtonState &bs, DeviceInput di, const RageTimer &now );
|
void CheckButtonChange( ButtonState &bs, DeviceInput di, const RageTimer &now );
|
||||||
|
|
||||||
InputEventArray queue;
|
InputEventArray queue;
|
||||||
|
|||||||
Reference in New Issue
Block a user