mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-08-22 15:11:31 +00:00
[idd] common: centralize nonzero sequences
This commit is contained in:
@@ -77,6 +77,7 @@
|
|||||||
<ClInclude Include="InputPipeProtocol.h" />
|
<ClInclude Include="InputPipeProtocol.h" />
|
||||||
<ClInclude Include="PipeMsg.h" />
|
<ClInclude Include="PipeMsg.h" />
|
||||||
<ClInclude Include="RefreshRate.h" />
|
<ClInclude Include="RefreshRate.h" />
|
||||||
|
<ClInclude Include="Seq.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets" />
|
<ImportGroup Label="ExtensionTargets" />
|
||||||
|
|||||||
@@ -44,5 +44,8 @@
|
|||||||
<ClInclude Include="RefreshRate.h">
|
<ClInclude Include="RefreshRate.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="Seq.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
54
idd/LGCommon/Seq.h
Normal file
54
idd/LGCommon/Seq.h
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
* Looking Glass
|
||||||
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
|
* https://looking-glass.io
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||||
|
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace Seq
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
T Next(T value)
|
||||||
|
{
|
||||||
|
static_assert(std::is_integral<T>::value &&
|
||||||
|
std::is_unsigned<T>::value && !std::is_same<T, bool>::value,
|
||||||
|
"sequence type must be an unsigned integer");
|
||||||
|
|
||||||
|
const T next = value + static_cast<T>(1);
|
||||||
|
return next ? next : static_cast<T>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T Inc(T& value)
|
||||||
|
{
|
||||||
|
value = Next(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T Take(T& value)
|
||||||
|
{
|
||||||
|
if (!value)
|
||||||
|
value = static_cast<T>(1);
|
||||||
|
const T result = value;
|
||||||
|
value = Next(value);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "capture/CFrameScheduler.h"
|
#include "capture/CFrameScheduler.h"
|
||||||
|
|
||||||
#include "CDebug.h"
|
#include "CDebug.h"
|
||||||
|
#include "Seq.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -210,8 +211,7 @@ bool CFrameScheduler::ElectOwner(uint64_t now, uint32_t resetClientID)
|
|||||||
{
|
{
|
||||||
if (m_scheduling)
|
if (m_scheduling)
|
||||||
{
|
{
|
||||||
if (!++m_epoch)
|
Seq::Inc(m_epoch);
|
||||||
++m_epoch;
|
|
||||||
m_schedule.epoch = m_epoch;
|
m_schedule.epoch = m_epoch;
|
||||||
}
|
}
|
||||||
m_nextDeadline = m_scheduling ? fastest->nextDelivery : 0;
|
m_nextDeadline = m_scheduling ? fastest->nextDelivery : 0;
|
||||||
@@ -517,8 +517,7 @@ void CFrameScheduler::AdvanceDeadlineSerial(uint64_t count)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
for (; epochAdvances; --epochAdvances)
|
for (; epochAdvances; --epochAdvances)
|
||||||
if (!++m_epoch)
|
Seq::Inc(m_epoch);
|
||||||
++m_epoch;
|
|
||||||
m_schedule.epoch = m_epoch;
|
m_schedule.epoch = m_epoch;
|
||||||
|
|
||||||
Client * client = FindClient(m_schedule.clientID);
|
Client * client = FindClient(m_schedule.clientID);
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "transport/CControlHub.h"
|
#include "transport/CControlHub.h"
|
||||||
|
|
||||||
#include "CDebug.h"
|
#include "CDebug.h"
|
||||||
|
#include "Seq.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@@ -105,12 +106,6 @@ DWORD WINAPI CControlHub::WorkerProc(void * opaque)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t CControlHub::NextRevision(uint64_t revision)
|
|
||||||
{
|
|
||||||
++revision;
|
|
||||||
return revision ? revision : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CControlHub::TokenMatches(
|
bool CControlHub::TokenMatches(
|
||||||
const Sink& sink, const ControlToken& token)
|
const Sink& sink, const ControlToken& token)
|
||||||
{
|
{
|
||||||
@@ -159,12 +154,12 @@ bool CControlHub::Add(
|
|||||||
selected->deliveredShape = 0;
|
selected->deliveredShape = 0;
|
||||||
selected->deliveredTransform = 0;
|
selected->deliveredTransform = 0;
|
||||||
memset(selected->retryAt, 0, sizeof(selected->retryAt));
|
memset(selected->retryAt, 0, sizeof(selected->retryAt));
|
||||||
selected->nextWork = 0;
|
selected->nextWork = 0;
|
||||||
selected->bindingSerial = NextRevision(selected->bindingSerial);
|
selected->bindingSerial = Seq::Next(selected->bindingSerial);
|
||||||
selected->replaySerial = NextRevision(selected->replaySerial);
|
selected->replaySerial = Seq::Next(selected->replaySerial);
|
||||||
selected->calling = false;
|
selected->calling = false;
|
||||||
selected->active = false;
|
selected->active = false;
|
||||||
selected->failed = false;
|
selected->failed = false;
|
||||||
selected->failurePending = false;
|
selected->failurePending = false;
|
||||||
}
|
}
|
||||||
control.SetControlEvents(this, token);
|
control.SetControlEvents(this, token);
|
||||||
@@ -174,10 +169,10 @@ bool CControlHub::Add(
|
|||||||
if (selected->target == &control && selected->backend == backend &&
|
if (selected->target == &control && selected->backend == backend &&
|
||||||
selected->epoch == epoch && selected->reserved && !selected->failed)
|
selected->epoch == epoch && selected->reserved && !selected->failed)
|
||||||
{
|
{
|
||||||
selected->replaySerial = NextRevision(selected->replaySerial);
|
selected->replaySerial = Seq::Next(selected->replaySerial);
|
||||||
selected->active = true;
|
selected->active = true;
|
||||||
selected->reserved = false;
|
selected->reserved = false;
|
||||||
attached = true;
|
attached = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!attached)
|
if (!attached)
|
||||||
@@ -285,7 +280,7 @@ void CControlHub::OnControlReplay(const ControlToken& token)
|
|||||||
sink.deliveredPosition = 0;
|
sink.deliveredPosition = 0;
|
||||||
sink.deliveredShape = 0;
|
sink.deliveredShape = 0;
|
||||||
sink.deliveredTransform = 0;
|
sink.deliveredTransform = 0;
|
||||||
sink.replaySerial = NextRevision(sink.replaySerial);
|
sink.replaySerial = Seq::Next(sink.replaySerial);
|
||||||
memset(sink.retryAt, 0, sizeof(sink.retryAt));
|
memset(sink.retryAt, 0, sizeof(sink.retryAt));
|
||||||
SetEvent(sink.wake);
|
SetEvent(sink.wake);
|
||||||
return;
|
return;
|
||||||
@@ -529,14 +524,14 @@ void CControlHub::SendCursor(const IDARG_OUT_QUERY_HWCURSOR& info,
|
|||||||
m_state.cursor.X = info.X;
|
m_state.cursor.X = info.X;
|
||||||
m_state.cursor.Y = info.Y;
|
m_state.cursor.Y = info.Y;
|
||||||
m_state.sdrWhiteLevel = sdrWhiteLevel;
|
m_state.sdrWhiteLevel = sdrWhiteLevel;
|
||||||
m_state.positionRevision = NextRevision(m_state.positionRevision);
|
m_state.positionRevision = Seq::Next(m_state.positionRevision);
|
||||||
|
|
||||||
if (shape)
|
if (shape)
|
||||||
{
|
{
|
||||||
m_state.cursor.IsCursorShapeUpdated = info.IsCursorShapeUpdated;
|
m_state.cursor.IsCursorShapeUpdated = info.IsCursorShapeUpdated;
|
||||||
m_state.cursor.CursorShapeInfo = info.CursorShapeInfo;
|
m_state.cursor.CursorShapeInfo = info.CursorShapeInfo;
|
||||||
m_state.cursorData = std::move(cursorData);
|
m_state.cursorData = std::move(cursorData);
|
||||||
m_state.shapeRevision = NextRevision(m_state.shapeRevision);
|
m_state.shapeRevision = Seq::Next(m_state.shapeRevision);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -550,8 +545,8 @@ void CControlHub::SetColorTransform(
|
|||||||
{
|
{
|
||||||
{
|
{
|
||||||
CSRWExclusiveLock lock(m_stateLock);
|
CSRWExclusiveLock lock(m_stateLock);
|
||||||
m_state.transform = std::move(transform);
|
m_state.transform = std::move(transform);
|
||||||
m_state.transformRevision = NextRevision(m_state.transformRevision);
|
m_state.transformRevision = Seq::Next(m_state.transformRevision);
|
||||||
}
|
}
|
||||||
WakeAll(WorkType::TRANSFORM);
|
WakeAll(WorkType::TRANSFORM);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,7 +104,6 @@ private:
|
|||||||
bool m_valid = false;
|
bool m_valid = false;
|
||||||
|
|
||||||
static DWORD WINAPI WorkerProc(void * opaque);
|
static DWORD WINAPI WorkerProc(void * opaque);
|
||||||
static uint64_t NextRevision(uint64_t revision);
|
|
||||||
static bool TokenMatches(const Sink& sink, const ControlToken& token);
|
static bool TokenMatches(const Sink& sink, const ControlToken& token);
|
||||||
|
|
||||||
bool BeginWork(Sink& sink, Work& work, DWORD& wait);
|
bool BeginWork(Sink& sink, Work& work, DWORD& wait);
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "transport/CInputHub.h"
|
#include "transport/CInputHub.h"
|
||||||
|
|
||||||
#include "input/IInputSink.h"
|
#include "input/IInputSink.h"
|
||||||
|
#include "Seq.h"
|
||||||
|
|
||||||
static bool SameClient(const SourceKey& left, const SourceKey& right)
|
static bool SameClient(const SourceKey& left, const SourceKey& right)
|
||||||
{
|
{
|
||||||
@@ -510,9 +511,7 @@ void CInputHub::InvalidateInteraction()
|
|||||||
|
|
||||||
void CInputHub::AdvanceInteractionSerial()
|
void CInputHub::AdvanceInteractionSerial()
|
||||||
{
|
{
|
||||||
++m_interactionSerial;
|
Seq::Inc(m_interactionSerial);
|
||||||
if (!m_interactionSerial)
|
|
||||||
++m_interactionSerial;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CInputHub::CheckState()
|
bool CInputHub::CheckState()
|
||||||
|
|||||||
@@ -20,6 +20,8 @@
|
|||||||
|
|
||||||
#include "transport/CRecoveryHub.h"
|
#include "transport/CRecoveryHub.h"
|
||||||
|
|
||||||
|
#include "Seq.h"
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
@@ -99,16 +101,6 @@ bool CRecoveryHub::ActionMatchesLocked(
|
|||||||
action.active == m_operation.action.active;
|
action.active == m_operation.action.active;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t CRecoveryHub::NextNonzero(uint64_t& value)
|
|
||||||
{
|
|
||||||
uint64_t result = value++;
|
|
||||||
if (!result)
|
|
||||||
result = value++;
|
|
||||||
if (!value)
|
|
||||||
++value;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t CRecoveryHub::NextSerial()
|
uint32_t CRecoveryHub::NextSerial()
|
||||||
{
|
{
|
||||||
uint32_t result = m_nextSerial;
|
uint32_t result = m_nextSerial;
|
||||||
@@ -134,7 +126,7 @@ void CRecoveryHub::SetWaitingLocked(Request& request,
|
|||||||
request.source = source;
|
request.source = source;
|
||||||
request.session = session;
|
request.session = session;
|
||||||
request.operation = operation;
|
request.operation = operation;
|
||||||
request.sequence = NextNonzero(m_nextSequence);
|
request.sequence = Seq::Take(m_nextSequence);
|
||||||
request.serial = serial;
|
request.serial = serial;
|
||||||
request.active = active;
|
request.active = active;
|
||||||
request.state = SlotState::WAITING;
|
request.state = SlotState::WAITING;
|
||||||
@@ -264,9 +256,9 @@ RecoveryAdmission CRecoveryHub::Submit(const SourceKey& source,
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_operation = Operation {};
|
m_operation = Operation {};
|
||||||
m_operation.phase = OperationPhase::IN_FLIGHT;
|
m_operation.phase = OperationPhase::IN_FLIGHT;
|
||||||
m_operation.id = NextNonzero(m_nextOperation);
|
m_operation.id = Seq::Take(m_nextOperation);
|
||||||
m_operation.action.route = NextNonzero(m_nextRoute);
|
m_operation.action.route = Seq::Take(m_nextRoute);
|
||||||
m_operation.action.session = m_session;
|
m_operation.action.session = m_session;
|
||||||
m_operation.action.serial = NextSerial();
|
m_operation.action.serial = NextSerial();
|
||||||
m_operation.action.active = active;
|
m_operation.action.active = active;
|
||||||
|
|||||||
@@ -106,7 +106,6 @@ private:
|
|||||||
unsigned FindSourceLocked(const SourceKey& source) const;
|
unsigned FindSourceLocked(const SourceKey& source) const;
|
||||||
unsigned FindFreeLocked() const;
|
unsigned FindFreeLocked() const;
|
||||||
bool ActionMatchesLocked(const RecoveryAction& action) const;
|
bool ActionMatchesLocked(const RecoveryAction& action) const;
|
||||||
uint64_t NextNonzero(uint64_t& value);
|
|
||||||
uint32_t NextSerial();
|
uint32_t NextSerial();
|
||||||
void ClearRequestLocked(Request& request);
|
void ClearRequestLocked(Request& request);
|
||||||
void SetWaitingLocked(Request& request, const SourceKey& source,
|
void SetWaitingLocked(Request& request, const SourceKey& source,
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "transport/CTransportManager.h"
|
#include "transport/CTransportManager.h"
|
||||||
|
|
||||||
#include "CDebug.h"
|
#include "CDebug.h"
|
||||||
|
#include "Seq.h"
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <new>
|
#include <new>
|
||||||
@@ -737,9 +738,7 @@ void CTransportManager::RetryEntry(Entry& entry, uint64_t now,
|
|||||||
entry.inputAbsent = false;
|
entry.inputAbsent = false;
|
||||||
entry.frameAbsent = false;
|
entry.frameAbsent = false;
|
||||||
entry.serviceRetryAt = 0;
|
entry.serviceRetryAt = 0;
|
||||||
++entry.epoch;
|
Seq::Inc(entry.epoch);
|
||||||
if (!entry.epoch)
|
|
||||||
++entry.epoch;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OpenEntry(entry) != OpenResult::SUCCESS)
|
if (OpenEntry(entry) != OpenResult::SUCCESS)
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include "transport/lgmp/CLGMPHost.h"
|
#include "transport/lgmp/CLGMPHost.h"
|
||||||
#include "CDebug.h"
|
#include "CDebug.h"
|
||||||
#include "CSRWLock.h"
|
#include "CSRWLock.h"
|
||||||
|
#include "Seq.h"
|
||||||
|
|
||||||
#include "common/KVMFRInput.h"
|
#include "common/KVMFRInput.h"
|
||||||
#include "common/LGMPConfig.h"
|
#include "common/LGMPConfig.h"
|
||||||
@@ -127,17 +128,16 @@ void CLGMPInputTransport::UpdateTargetState(
|
|||||||
const InputTargetState& state)
|
const InputTargetState& state)
|
||||||
{
|
{
|
||||||
CSRWExclusiveLock lock(m_statusLock);
|
CSRWExclusiveLock lock(m_statusLock);
|
||||||
if (state.state == m_targetState.state &&
|
if (state.state == m_targetState.state &&
|
||||||
state.available == m_targetState.available &&
|
state.available == m_targetState.available &&
|
||||||
state.owned == m_targetState.owned &&
|
state.owned == m_targetState.owned &&
|
||||||
state.owner.client == m_targetState.owner.client &&
|
state.owner.client == m_targetState.owner.client &&
|
||||||
state.owner.generation == m_targetState.owner.generation)
|
state.owner.generation == m_targetState.owner.generation)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (state.state != m_targetState.state)
|
if (state.state != m_targetState.state)
|
||||||
{
|
{
|
||||||
if (++m_endpointGeneration == 0)
|
Seq::Inc(m_endpointGeneration);
|
||||||
++m_endpointGeneration;
|
|
||||||
}
|
}
|
||||||
m_targetState = state;
|
m_targetState = state;
|
||||||
m_statusDirty = true;
|
m_statusDirty = true;
|
||||||
@@ -183,9 +183,7 @@ bool CLGMPInputTransport::PublishStatus()
|
|||||||
status.maxButtons = KVMFR_INPUT_MOUSE_BUTTON_COUNT;
|
status.maxButtons = KVMFR_INPUT_MOUSE_BUTTON_COUNT;
|
||||||
memcpy(lgmpHostMemPtr(memory), &status, sizeof(status));
|
memcpy(lgmpHostMemPtr(memory), &status, sizeof(status));
|
||||||
|
|
||||||
uint32_t serial = m_statusSerial + 1;
|
const uint32_t serial = Seq::Next(m_statusSerial);
|
||||||
if (!serial)
|
|
||||||
++serial;
|
|
||||||
const LGMP_STATUS result = lgmpHostQueuePost(m_queue, serial, memory);
|
const LGMP_STATUS result = lgmpHostQueuePost(m_queue, serial, memory);
|
||||||
if (result == LGMP_OK)
|
if (result == LGMP_OK)
|
||||||
{
|
{
|
||||||
@@ -263,8 +261,7 @@ bool CLGMPInputTransport::Start(IInputTarget& target)
|
|||||||
{
|
{
|
||||||
CSRWExclusiveLock statusLock(m_statusLock);
|
CSRWExclusiveLock statusLock(m_statusLock);
|
||||||
m_targetState = target.GetState({});
|
m_targetState = target.GetState({});
|
||||||
if (++m_endpointGeneration == 0)
|
Seq::Inc(m_endpointGeneration);
|
||||||
++m_endpointGeneration;
|
|
||||||
m_statusDirty = true;
|
m_statusDirty = true;
|
||||||
}
|
}
|
||||||
m_statusFailed.store(false, std::memory_order_release);
|
m_statusFailed.store(false, std::memory_order_release);
|
||||||
@@ -505,9 +502,7 @@ bool CLGMPInputTransport::ProcessMessage(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t expectedSequence = m_ownerSequence + 1;
|
const uint32_t expectedSequence = Seq::Next(m_ownerSequence);
|
||||||
if (!expectedSequence)
|
|
||||||
expectedSequence = 1;
|
|
||||||
if (message.sequence != expectedSequence)
|
if (message.sequence != expectedSequence)
|
||||||
{
|
{
|
||||||
++m_statistics.sequenceErrors;
|
++m_statistics.sequenceErrors;
|
||||||
|
|||||||
Reference in New Issue
Block a user