Lumiera  0.pre.03
»edit your freedom«
looper.hpp
Go to the documentation of this file.
1 /*
2  LOOPER.hpp - steam dispatcher loop and timing control logic
3 
4  Copyright (C)
5  2016, Hermann Vosseler <Ichthyostega@web.de>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 */
13 
14 
40 #ifndef STEAM_CONTROL_LOOPER_H
41 #define STEAM_CONTROL_LOOPER_H
42 
43 #include "lib/time/timevalue.hpp"
44 #include "vault/real-clock.hpp"
45 
46 #include <functional>
47 #include <chrono>
48 
49 
50 
51 namespace steam {
52 namespace control {
53 
54  using lib::time::Time;
55  using lib::time::TimeVar;
56  using lib::time::Offset;
57  using lib::time::Duration;
58  using std::chrono::milliseconds;
59  using vault::RealClock;
60 
61  namespace {
71 
81  }
82 
83 
84 
105  class Looper
106  {
107  using Predicate = std::function<bool(void)>;
108 
109  bool shutdown_ = false;
110  bool disabled_ = false;
111  bool inChange_ = false;
112  bool hasWork_ = false;
113  bool isDirty_ = false;
114 
115  TimeVar gotDirty_ = Time::NEVER;
116 
117  Predicate hasCommandsPending_;
118 
119 
120  public:
121  template<class FUN>
122  Looper(FUN determine_commands_are_waiting)
123  : hasCommandsPending_(determine_commands_are_waiting)
124  { }
125 
126  // standard copy acceptable
127 
128 
129  /* == working state logic == */
130 
131  bool isDying() const { return shutdown_; }
132  bool isDisabled() const { return disabled_ or isDying(); }
133  bool useTimeout() const { return isDirty_ and not isDisabled(); }
134  bool isWorking() const { return hasWork_ and not isDisabled(); }
135  bool idleBuild() const { return isDirty_ and not hasWork_; }
136  bool runBuild() const { return (idleBuild() or forceBuild()) and not isDisabled(); }
137  bool isIdle() const { return not (isWorking() or runBuild() or isDisabled()); }
138 
139 
140  /* == operation control == */
141 
142  void
143  triggerShutdown()
144  {
145  shutdown_ = true;
146  }
147 
148  void
149  enableProcessing(bool yes =true)
150  {
151  disabled_ = not yes;
152  }
153 
164  void
166  {
167  inChange_ = false;
168  if (runBuild())
169  isDirty_ = false; // assume the builder has been triggered in the loop body
170  }
171 
172  bool
174  {
175  return inChange_;
176  }
177 
179  bool
181  {
182  hasWork_ = hasCommandsPending_();
183  bool proceedImmediately = isWorking() or forceBuild() or isDying();
184  inChange_ = proceedImmediately or useTimeout();
185 
186  if (isWorking() and not isDirty_)
187  { // schedule Builder run after timeout
188  startBuilderTimeout();
189  isDirty_ = true;
190  }
191 
192  return proceedImmediately;
193  }
194 
196  bool
197  shallLoop() const
198  {
199  return not isDying();
200  }
201 
202  milliseconds
203  getTimeout() const
204  {
205  if (not useTimeout())
206  return milliseconds::zero();
207  else
208  return milliseconds{
210  * (isDirty_ and not isWorking()? 1 : slowdownFactor())};
211  }
212 
213 
214  private:
215  static uint wakeTimeout_ms();
216  static uint slowdownFactor();
217 
218  void startBuilderTimeout();
219  bool forceBuild() const;
220  };
221 
222 
223 
235  inline uint
237  {
239  }
240 
241  inline uint
242  Looper::slowdownFactor()
243  {
245  }
246 
247  inline void
248  Looper::startBuilderTimeout()
249  {
250  gotDirty_ = RealClock::now();
251  }
252 
256  inline bool
258  {
259  static Duration maxBuildTimeout{Time(wakeTimeout_ms() * slowdownFactor(), 0)};
260 
261  return isDirty_
262  and maxBuildTimeout < Offset(gotDirty_, RealClock::now());
263  }
264 
265 
266 
267 }} // namespace steam::control
268 #endif /*STEAM_CONTROL_LOOPER_H*/
a mutable time value, behaving like a plain number, allowing copy and re-accessing ...
Definition: timevalue.hpp:232
const uint STEAM_DISPATCHER_BUSY_SLOWDOWN_FACTOR
Factor to slow down the latency when the command queue is not empty.
Definition: looper.hpp:80
bool hasPendingChanges() const
< "check point"
Definition: looper.hpp:173
const uint STEAM_DISPATCHER_BUILDER_DELAY_ms
Latency to trigger the Builder after processing command(s).
Definition: looper.hpp:70
bool forceBuild() const
Definition: looper.hpp:257
Steam-Layer implementation namespace root.
bool shallLoop() const
state fusion to control looping
Definition: looper.hpp:197
bool requireAction()
state fusion to control (timed) wait
Definition: looper.hpp:180
Lumiera&#39;s internal time value datatype.
Definition: timevalue.hpp:299
void markStateProcessed()
invoking this function signals that all consequences of past state changes have been processed and ar...
Definition: looper.hpp:165
static const Time NEVER
border condition marker value. NEVER >= any time value
Definition: timevalue.hpp:314
Offset measures a distance in time.
Definition: timevalue.hpp:358
Duration is the internal Lumiera time metric.
Definition: timevalue.hpp:468
Encapsulated control logic for the session thread loop.
Definition: looper.hpp:105
Convenience frontend to access the current raw system time.
Definition: real-clock.hpp:45
a family of time value like entities and their relationships.
Front-end for simplified access to the current wall clock time.
static uint wakeTimeout_ms()
Definition: looper.hpp:236