Cockatrice 2026-09-01-Development-3.1.0-beta.10
A virtual tabletop for multiplayer card games
Loading...
Searching...
No Matches
LagMonitor Class Reference

Detects main-thread event loop stalls ("UI freezes") from the inside. More...

#include <lag_monitor.h>

Inheritance diagram for LagMonitor:
[legend]
Collaboration diagram for LagMonitor:
[legend]

Classes

struct  StallRecord

Public Member Functions

 LagMonitor (QObject *parent=nullptr)
QList< StallRecordrecentStalls () const
 Stalls recorded during this session, oldest first.
void clearStalls ()
void recordGap (qint64 gapMs)
 Feeds a measured tick-to-tick gap through the detection logic.

Static Public Attributes

static constexpr int TICK_INTERVAL_MS = 500
static constexpr int STALL_THRESHOLD_MS = 2000
static constexpr int MAX_RECORDED_STALLS = 32
static constexpr qint64 MAX_PLAUSIBLE_STALL_MS = 600000
 Gaps beyond this are treated as suspend artifacts rather than stalls.

Protected Member Functions

bool eventFilter (QObject *obj, QEvent *event) override

Private Slots

void checkTick ()

Private Attributes

QTimer * timer
QElapsedTimer tickClock
 monotonic clock, so wall clock steps do not fabricate stalls
QList< StallRecordstalls

Detailed Description

Detects main-thread event loop stalls ("UI freezes") from the inside.

A timer is expected to fire every TICK_INTERVAL_MS of wall time. When the observed gap greatly exceeds that interval, some other task blocked the event loop for roughly the overshooting duration. This is what separates "my client froze" from "the network is lagging" in user reports.

Gaps that span an application state change (suspend, minimize, focus loss) are discarded, and implausibly huge gaps are dropped, so operating system power events do not fabricate stalls. This handling is load-bearing on Windows, where the monotonic clock used by Qt counts sleep time.

Healthy operation costs one timer wakeup per tick and two integer comparisons. Allocations happen only when a stall is actually recorded.

Constructor & Destructor Documentation

◆ LagMonitor()

LagMonitor::LagMonitor ( QObject * parent = nullptr)
explicit
Here is the call graph for this function:

Member Function Documentation

◆ checkTick

void LagMonitor::checkTick ( )
privateslot
Here is the call graph for this function:
Here is the caller graph for this function:

◆ clearStalls()

void LagMonitor::clearStalls ( )

◆ eventFilter()

bool LagMonitor::eventFilter ( QObject * obj,
QEvent * event )
overrideprotected

◆ recentStalls()

QList< LagMonitor::StallRecord > LagMonitor::recentStalls ( ) const

Stalls recorded during this session, oldest first.

Intended consumers are log output and the diagnostics export. The list holds at most MAX_RECORDED_STALLS entries.

◆ recordGap()

void LagMonitor::recordGap ( qint64 gapMs)

Feeds a measured tick-to-tick gap through the detection logic.

Split out of checkTick so threshold, plausibility, and trim behavior stay unit-testable without real timing.

Here is the caller graph for this function:

Member Data Documentation

◆ MAX_PLAUSIBLE_STALL_MS

qint64 LagMonitor::MAX_PLAUSIBLE_STALL_MS = 600000
staticconstexpr

Gaps beyond this are treated as suspend artifacts rather than stalls.

◆ MAX_RECORDED_STALLS

int LagMonitor::MAX_RECORDED_STALLS = 32
staticconstexpr

◆ STALL_THRESHOLD_MS

int LagMonitor::STALL_THRESHOLD_MS = 2000
staticconstexpr

◆ stalls

QList<StallRecord> LagMonitor::stalls
private

◆ TICK_INTERVAL_MS

int LagMonitor::TICK_INTERVAL_MS = 500
staticconstexpr

◆ tickClock

QElapsedTimer LagMonitor::tickClock
private

monotonic clock, so wall clock steps do not fabricate stalls

◆ timer

QTimer* LagMonitor::timer
private

The documentation for this class was generated from the following files: