DetectorGraph  2.0
timeoutpublisherservice.cpp
Go to the documentation of this file.
1 // Copyright 2017 Nest Labs, Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
16 
17 namespace DetectorGraph
18 {
19 
20 TimeoutPublisherService::TimeoutPublisherService(Graph& arGraph) : mrGraph(arGraph), mMetronomePeriodMsec(0)
21 {
22 }
23 
25 {
26 // The Lite version's allocator automatically deletes all objects using RAII
27 #if !defined(BUILD_FEATURE_DETECTORGRAPH_CONFIG_LITE)
28  for (TimeoutDispatchersContainer::iterator tZombieDataIt = mTimeoutDispatchers.begin();
29  tZombieDataIt != mTimeoutDispatchers.end();
30  ++tZombieDataIt)
31  {
32  delete *tZombieDataIt;
33  }
34 
35  for (PeriodicPublishingSeriesContainer::iterator tZombieDataIt = mPeriodicSeries.begin();
36  tZombieDataIt != mPeriodicSeries.end();
37  ++tZombieDataIt)
38  {
39  delete tZombieDataIt->mpDispatcher;
40  }
41 #endif
42 }
43 
45 {
46  TimeoutPublisherHandle newHandle = (TimeoutPublisherHandle)mTimeoutDispatchers.size();
47  mTimeoutDispatchers.push_back(NULL);
48 #if defined(BUILD_FEATURE_DETECTORGRAPH_CONFIG_INSTRUMENT_RESOURCE_USAGE)
49  DG_LOG("Reserved UniqueTimerHandle=%d\n", (int)newHandle);
50 #endif
51  return newHandle;
52 }
53 
54 void TimeoutPublisherService::ScheduleTimeoutDispatcher(
55  DispatcherInterface* aDispatcher,
56  const TimeOffset aMillisecondsFromNow,
57  const TimeoutPublisherHandle aHandle)
58 {
59  // Assert valid Handle
60  DG_ASSERT(0 <= aHandle && (unsigned)aHandle < mTimeoutDispatchers.size());
61  unsigned dispatcherIdx = (unsigned)aHandle;
62  // Assert dispatcher is available
63  DG_ASSERT(mTimeoutDispatchers[dispatcherIdx] == NULL);
64  mTimeoutDispatchers[dispatcherIdx] = aDispatcher;
65  SetTimeout(aMillisecondsFromNow, aHandle);
66  Start(aHandle);
67 }
68 
69 void TimeoutPublisherService::SchedulePeriodicPublishingDispatcher(
70  DispatcherInterface* aDispatcher,
71  const TimeOffset aPeriodInMilliseconds)
72 {
73  mMetronomePeriodMsec = gcd(aPeriodInMilliseconds, mMetronomePeriodMsec);
74  mPeriodicSeries.push_back(
75  PeriodicPublishingSeries(aPeriodInMilliseconds, aDispatcher));
76 }
77 
79 {
80  // Assert valid Handle
81  DG_ASSERT(0 <= aHandle && (unsigned)aHandle < mTimeoutDispatchers.size());
82  unsigned dispatcherIdx = (unsigned)aHandle;
83  DispatcherInterface* tDispatcher = mTimeoutDispatchers[dispatcherIdx];
84 
85  if (tDispatcher)
86  {
87  Cancel(aHandle);
88 
89 #if defined(BUILD_FEATURE_DETECTORGRAPH_CONFIG_LITE)
90  mTimeoutDispatchersAllocator.Delete(tDispatcher);
91 #else
92  delete tDispatcher;
93 #endif
94  mTimeoutDispatchers[dispatcherIdx] = NULL;
95  }
96 }
97 
99 {
100  // Assert valid Handle
101  DG_ASSERT(0 <= aHandle && (unsigned)aHandle < mTimeoutDispatchers.size());
102  unsigned dispatcherIdx = (unsigned)aHandle;
103  DispatcherInterface* tDispatcher = mTimeoutDispatchers[dispatcherIdx];
104  if (tDispatcher)
105  {
106  tDispatcher->Dispatch(mrGraph);
107 #if defined(BUILD_FEATURE_DETECTORGRAPH_CONFIG_LITE)
108  mTimeoutDispatchersAllocator.Delete(tDispatcher);
109 #else
110  delete tDispatcher;
111 #endif
112  mTimeoutDispatchers[dispatcherIdx] = NULL;
113  }
114 }
115 
117 {
118  // Assert valid Handle
119  DG_ASSERT(0 <= aHandle && (unsigned)aHandle < mTimeoutDispatchers.size());
120  unsigned dispatcherIdx = (unsigned)aHandle;
121  return (mTimeoutDispatchers[dispatcherIdx] == NULL);
122 }
123 
125 {
126  if (mMetronomePeriodMsec > 0)
127  {
128  StartMetronome(mMetronomePeriodMsec);
129 #if defined(BUILD_FEATURE_DETECTORGRAPH_CONFIG_INSTRUMENT_RESOURCE_USAGE)
130  DG_LOG("Started Metronome with period of %d milliseconds\n", mMetronomePeriodMsec);
131 #endif
132  }
133 }
134 
136 {
137  for (PeriodicPublishingSeriesContainer::iterator it = mPeriodicSeries.begin();
138  it != mPeriodicSeries.end();
139  ++it)
140  {
141  it->mMetronomeAccumulator += mMetronomePeriodMsec;
142  if (it->mMetronomeAccumulator >= it->mPublishingPeriodMsec)
143  {
144  it->mpDispatcher->Dispatch(mrGraph);
145  it->mMetronomeAccumulator = 0;
146  }
147  }
148 }
149 
150 TimeOffset TimeoutPublisherService::gcd(TimeOffset lhs, TimeOffset rhs)
151 {
152  while (rhs != 0)
153  {
154  TimeOffset temp = rhs;
155 #if defined(DG_TIMEOFFSET_REMAINDER)
156  rhs = DG_TIMEOFFSET_REMAINDER(lhs, rhs);
157 #else
158  rhs = lhs % rhs;
159 #endif
160  lhs = temp;
161  }
162  return lhs;
163 }
164 
165 } // namespace DetectorGraph
bool HasTimeoutExpired(const TimeoutPublisherHandle aTimerHandle) const
Returns weather the timeout for a given handle has expired/fired already.
void CancelPublishOnTimeout(const TimeoutPublisherHandle aTimerHandle)
Cancels a timeout and deletes the stored TopicState.
virtual void Start(const TimeoutPublisherHandle)=0
Should start a timer for the given handle.
Implements a graph of Topics & Detectors with Input/Output APIs.
Definition: graph.hpp:127
TimeoutPublisherHandle GetUniqueTimerHandle()
Returns a unique id/handle for a new timer.
TimeoutPublisherService(Graph &graph)
Constructor that initializes the service connected to a graph.
virtual void SetTimeout(const TimeOffset aMillisecondsFromNow, const TimeoutPublisherHandle)=0
Should setup a timeout for the given handle.
void DG_LOG(const char *aLogString,...)
Definition: dglogging.cpp:22
virtual void StartMetronome(const TimeOffset aPeriodInMilliseconds)=0
Should start the metronome (periodic timer) for the given period.
void StartPeriodicPublishing()
Starts a Metronome to publish scheduled TopicStates.
void TimeoutExpired(const TimeoutPublisherHandle aTimerHandle)
Fires/Dispatches a TopicState that was pending on a timeout.
void MetronomeFired()
Update metronome counters and Fires/Dispatches TopicStates that was pending on scheduled period...
virtual void Cancel(const TimeoutPublisherHandle)=0
Should cancel the timer the given handle.
#define DG_ASSERT(condition)
Definition: dgassert.hpp:20