1//============================================================================
2//
3// SSSS tt lll lll
4// SS SS tt ll ll
5// SS tttttt eeee ll ll aaaa
6// SSSS tt ee ee ll ll aa
7// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
8// SS SS tt ee ll ll aa aa
9// SSSS ttt eeeee llll llll aaaaa
10//
11// Copyright (c) 1995-2019 by Bradford W. Mott, Stephen Anthony
12// and the Stella Team
13//
14// See the file "License.txt" for information on usage and redistribution of
15// this file, and for a DISCLAIMER OF ALL WARRANTIES.
16//============================================================================
17
18#ifndef STAGGERED_LOGGER
19#define STAGGERED_LOGGER
20
21#include <functional>
22#include <chrono>
23#include <thread>
24#include <mutex>
25
26#include "bspf.hxx"
27#include "TimerManager.hxx"
28#include "Logger.hxx"
29/**
30 * This class buffers log events and logs them after a certain time window has expired.
31 * The timout increases after every log line by a factor of two until a maximum is reached.
32 * If no events are reported, the window size decreases again.
33 */
34
35class StaggeredLogger {
36 public:
37
38 StaggeredLogger(const string& message, Logger::Level level);
39
40 ~StaggeredLogger();
41
42 void log();
43
44 private:
45
46 void _log();
47
48 void onTimerExpired(uInt32 timerId);
49
50 void startInterval();
51
52 void increaseInterval();
53
54 void decreaseInterval();
55
56 void logLine();
57
58 string myMessage;
59 Logger::Level myLevel;
60
61 uInt32 myCurrentEventCount;
62 bool myIsCurrentlyCollecting;
63
64 std::chrono::high_resolution_clock::time_point myLastIntervalStartTimestamp;
65 std::chrono::high_resolution_clock::time_point myLastIntervalEndTimestamp;
66
67 uInt32 myCurrentIntervalSize;
68 uInt32 myMaxIntervalFactor;
69 uInt32 myCurrentIntervalFactor;
70 uInt32 myCooldownTime;
71
72 std::mutex myMutex;
73
74 // We need control over the destruction porcess and over the exact point where
75 // the worker thread joins -> allocate on the heap end delete explicitly in
76 // our destructor.
77 TimerManager *myTimer;
78 TimerManager::TimerId myTimerId;
79
80 // It is possible that the timer callback is running even after TimerManager::clear
81 // returns. This id is unique per timer and is used to return from the callback
82 // early in case the time is stale.
83 uInt32 myTimerCallbackId;
84};
85
86#endif // STAGGERED_LOGGER
87