Refactor SMXManager::SendLightUpdates to queue multiple lights commands if possible.
This also fixes a memory leak if lights are queued too quickly.
This commit is contained in:
parent
0c19451d7d
commit
69b2239922
@ -486,27 +486,47 @@ void SMX::SMXManager::ReenableAutoLights()
|
||||
void SMX::SMXManager::SendLightUpdates()
|
||||
{
|
||||
g_Lock.AssertLockedByCurrentThread();
|
||||
if(m_aPendingLightsCommands.empty())
|
||||
return;
|
||||
|
||||
const PendingCommand &command = m_aPendingLightsCommands[0];
|
||||
|
||||
// See if it's time to send the next command. We only need to look at the first
|
||||
// command, since these are always sorted.
|
||||
if(command.fTimeToSend > GetMonotonicTime())
|
||||
|
||||
// If previous lights commands are being sent, wait for them to complete before
|
||||
// queueing more.
|
||||
if(m_iLightsCommandsInProgress > 0)
|
||||
return;
|
||||
|
||||
// If we have more than one command queued, we can queue several of them if we're
|
||||
// before fTimeToSend. For the V4 pads that require more commands, this lets us queue
|
||||
// the whole lights update at once. V3 pads require us to time commands, so we can't
|
||||
// spam both lights commands at once, which is handled by fTimeToSend.
|
||||
while( !m_aPendingLightsCommands.empty() )
|
||||
{
|
||||
// Send the lights command for each pad. If either pad isn't connected, this won't do
|
||||
// anything.
|
||||
const PendingCommand &command = m_aPendingLightsCommands[0];
|
||||
|
||||
// See if it's time to send this command.
|
||||
if(command.fTimeToSend > GetMonotonicTime())
|
||||
break;
|
||||
|
||||
for(int iPad = 0; iPad < 2; ++iPad)
|
||||
{
|
||||
if(!command.sPadCommand[iPad].empty())
|
||||
m_pDevices[iPad]->SendCommandLocked(command.sPadCommand[iPad]);
|
||||
{
|
||||
// Count the number of commands we've queued. We won't send any more until
|
||||
// this reaches 0 and all queued commands were sent.
|
||||
m_iLightsCommandsInProgress++;
|
||||
|
||||
// The completion callback is guaranteed to always be called, even if the controller
|
||||
// disconnects and the command wasn't sent.
|
||||
m_pDevices[iPad]->SendCommandLocked(command.sPadCommand[iPad], [this, iPad](string response) {
|
||||
g_Lock.AssertLockedByCurrentThread();
|
||||
m_iLightsCommandsInProgress--;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the command we've sent.
|
||||
m_aPendingLightsCommands.erase(m_aPendingLightsCommands.begin(), m_aPendingLightsCommands.begin()+1);
|
||||
}
|
||||
}
|
||||
|
||||
void SMX::SMXManager::SetPanelTestMode(PanelTestMode mode)
|
||||
{
|
||||
|
@ -76,6 +76,7 @@ private:
|
||||
string sPadCommand[2];
|
||||
};
|
||||
vector<PendingCommand> m_aPendingLightsCommands;
|
||||
int m_iLightsCommandsInProgress = 0;
|
||||
double m_fDelayLightCommandsUntil = 0;
|
||||
|
||||
// Panel test mode. This is separate from the sensor test mode (pressure display),
|
||||
|
Loading…
x
Reference in New Issue
Block a user