Stroika Library 3.0d25
 
Loading...
Searching...
No Matches
IdleManager.cpp
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2026. All rights reserved
3 */
4#include "Stroika/Frameworks/StroikaPreComp.h"
5
6#include <algorithm>
7
9
10#include "IdleManager.h"
11
12using namespace Stroika::Foundation;
13using namespace Stroika::Frameworks;
14using namespace Stroika::Frameworks::Led;
15
16/*
17 ********************************************************************************
18 ************************************ Idler *************************************
19 ********************************************************************************
20 */
21void Idler::SpendIdleTime ()
22{
23}
24
25/*
26 ********************************************************************************
27 ******************************* EnterIdler *************************************
28 ********************************************************************************
29 */
30void EnterIdler::OnEnterIdle ()
31{
32}
33
34/*
35 ********************************************************************************
36 ********************************** IdleManager *********************************
37 ********************************************************************************
38 */
39
40void IdleManager::AddIdler (Idler* idler)
41{
42 RequireNotNull (idler);
43 Require (fIdlers.find (idler) == fIdlers.end ());
44 IdlerInfo idlerInfo;
45 fIdlers.insert (map<Idler*, IdlerInfo>::value_type (idler, idlerInfo));
46}
47
48void IdleManager::RemoveIdler (Idler* idler)
49{
50 RequireNotNull (idler);
51 map<Idler*, IdlerInfo>::iterator i = fIdlers.find (idler);
52 Require (i != fIdlers.end ());
53 Assert (i->first == idler);
54 fIdlers.erase (i);
55}
56
57void IdleManager::AddEnterIdler (EnterIdler* enterIdler)
58{
59 RequireNotNull (enterIdler);
60 Require (find (fEnterIdlers.begin (), fEnterIdlers.end (), enterIdler) == fEnterIdlers.end ());
61 fEnterIdlers.push_back (enterIdler);
62 UpdateIdleMgrImplState ();
63}
64
65void IdleManager::RemoveEnterIdler (EnterIdler* enterIdler)
66{
67 RequireNotNull (enterIdler);
68 vector<EnterIdler*>::iterator i = find (fEnterIdlers.begin (), fEnterIdlers.end (), enterIdler);
69 Require (i != fEnterIdlers.end ());
70 Assert (*i == enterIdler);
71 fEnterIdlers.erase (i);
72 UpdateIdleMgrImplState ();
73}
74
75Time::DurationSeconds IdleManager::GetIdlerFrequncy (Idler* idler)
76{
77 RequireNotNull (idler);
78 map<Idler*, IdlerInfo>::iterator i = fIdlers.find (idler);
79 Require (i != fIdlers.end ());
80 Assert (i->first == idler);
81 return i->second.fIdlerFrequency;
82}
83
84void IdleManager::SetIdlerFrequncy (Idler* idler, Time::DurationSeconds idlerFrequency)
85{
86 RequireNotNull (idler);
87 map<Idler*, IdlerInfo>::iterator i = fIdlers.find (idler);
88 Require (i != fIdlers.end ());
89 Assert (i->first == idler);
90 if (i->second.fIdlerFrequency != idlerFrequency) {
91 i->second.fIdlerFrequency = idlerFrequency;
92 UpdateIdleMgrImplState ();
93 }
94}
95
96void IdleManager::UpdateIdleMgrImplState ()
97{
98 if (fIdleManagerOSImpl != nullptr) {
99 Time::DurationSeconds idleFreq = kNeverCallIdler;
100 for (auto i = fIdlers.begin (); i != fIdlers.end (); ++i) {
101 idleFreq = min (idleFreq, i->second.fIdlerFrequency);
102 }
103 if (not fEnterIdlers.empty ()) {
104 const Time::DurationSeconds kMinEnterIdleFreqCheck = 0.5s;
105 idleFreq = min (idleFreq, kMinEnterIdleFreqCheck);
106 }
107 bool shouldNeedIdleMgr = (idleFreq != kNeverCallIdler);
108 if (shouldNeedIdleMgr != fNeedMgrIdleCalls or (shouldNeedIdleMgr and idleFreq != fIdleManagerOSImpl->GetSuggestedFrequency ())) {
109 fNeedMgrIdleCalls = shouldNeedIdleMgr;
110 if (fNeedMgrIdleCalls) {
111 fIdleManagerOSImpl->SetSuggestedFrequency (idleFreq);
112 fIdleManagerOSImpl->StartSpendTimeCalls ();
113 }
114 else {
115 fIdleManagerOSImpl->TerminateSpendTimeCalls ();
116 }
117 }
118 }
119}
120
121void IdleManager::CallSpendTime ()
122{
123 SetInIdleMode (true); // not SURE this is the best place to call this - maybe SB called from OSREP only???
124 Foundation::Time::TimePointSeconds now = Time::GetTickCount ();
125 for (auto i = fIdlers.begin (); i != fIdlers.end (); ++i) {
126 // only call SpendTime if its been requested
127 if (i->second.fLastCalledAt + i->second.fIdlerFrequency <= now) {
128 Idler* idler = i->first;
129 idler->SpendIdleTime ();
130 now = Time::GetTickCount (); // update 'now' since we could have spent alot of time in 'SpendIdleTime'
131 i->second.fLastCalledAt = now;
132 }
133 }
134}
135
136void IdleManager::CallEnterIdle ()
137{
138 for (auto i = fEnterIdlers.begin (); i != fEnterIdlers.end (); ++i) {
139 EnterIdler* enterIdler = *i;
140 AssertNotNull (enterIdler);
141 enterIdler->OnEnterIdle ();
142 }
143}
144
145void IdleManager::SetIdleManagerOSImpl (IdleManagerOSImpl* impl)
146{
147 // If they are just setting the IMPL to nullptr and sThe is nullptr, then don't bother
148 // creating it (cuz at destruction time - these destructors could get done in any order,
149 // and forcing a create here could create an artificail memory block left over that looks
150 // to the memory leak detector - like a memory leak.
151 if (impl == nullptr) {
152 Get ().fIdleManagerOSImpl = nullptr;
153 }
154 else {
155 Get ().fIdleManagerOSImpl = impl;
156 }
157}
158
159/*
160 ********************************************************************************
161 ************************** IdleManager::IdleManagerOSImpl **********************
162 ********************************************************************************
163 */
164void IdleManager::IdleManagerOSImpl::CallSpendTime ()
165{
166 IdleManager::Get ().CallSpendTime ();
167}
#define AssertNotNull(p)
Definition Assertions.h:336
#define RequireNotNull(p)
Definition Assertions.h:350
time_point< RealtimeClock, DurationSeconds > TimePointSeconds
TimePointSeconds is a simpler approach to chrono::time_point, which doesn't require using templates e...
Definition Realtime.h:82
chrono::duration< double > DurationSeconds
chrono::duration<double> - a time span (length of time) measured in seconds, but high precision.
Definition Realtime.h:57