AlexaClientSDK  1.26.0
A cross-platform, modular SDK for interacting with the Alexa Voice Service
Timer.h
Go to the documentation of this file.
1 /*
2  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License").
5  * You may not use this file except in compliance with the License.
6  * A copy of the License is located at
7  *
8  * http://aws.amazon.com/apache2.0/
9  *
10  * or in the "license" file accompanying this file. This file is distributed
11  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12  * express or implied. See the License for the specific language governing
13  * permissions and limitations under the License.
14  */
15 
16 #ifndef ALEXA_CLIENT_SDK_AVSCOMMON_UTILS_INCLUDE_AVSCOMMON_UTILS_TIMING_TIMER_H_
17 #define ALEXA_CLIENT_SDK_AVSCOMMON_UTILS_INCLUDE_AVSCOMMON_UTILS_TIMING_TIMER_H_
18 
19 #include <chrono>
20 #include <condition_variable>
21 #include <functional>
22 #include <future>
23 #include <mutex>
24 #include <thread>
25 
30 
31 namespace alexaClientSDK {
32 namespace avsCommon {
33 namespace utils {
34 namespace timing {
35 
39 class Timer {
40 public:
45  static const size_t FOREVER = 0;
46 
48  enum class PeriodType {
57  ABSOLUTE,
58 
63  RELATIVE
64  };
65 
71  Timer(
72  std::shared_ptr<sdkInterfaces::timing::TimerDelegateFactoryInterface> timerDelegateFactory =
73  avs::initialization::SDKPrimitivesProvider::getInstance()->getTimerDelegateFactory());
74 
78  ~Timer();
79 
81  static size_t getForever() {
82  return FOREVER;
83  }
84 
86  static std::string getTag() {
87  return "Timer";
88  }
89 
113  template <typename Rep, typename Period, typename Task, typename... Args>
114  bool start(
115  const std::chrono::duration<Rep, Period>& delay,
116  const std::chrono::duration<Rep, Period>& period,
117  PeriodType periodType,
118  size_t maxCount,
119  Task task,
120  Args&&... args);
121 
143  template <typename Rep, typename Period, typename Task, typename... Args>
144  bool start(
145  const std::chrono::duration<Rep, Period>& period,
146  PeriodType periodType,
147  size_t maxCount,
148  Task task,
149  Args&&... args);
150 
169  template <typename Rep, typename Period, typename Task, typename... Args>
170  auto start(const std::chrono::duration<Rep, Period>& delay, Task task, Args&&... args)
171  -> std::future<decltype(task(args...))>;
172 
181  void stop();
182 
190  bool isActive() const;
191 
192 private:
198  bool activate();
199 
214  template <typename Rep, typename Period>
215  void callTask(
216  std::chrono::duration<Rep, Period> delay,
217  std::chrono::duration<Rep, Period> period,
218  PeriodType periodType,
219  size_t maxCount,
220  std::function<void()> task);
221 
223  mutable std::mutex m_mutex;
224 
226  std::unique_ptr<sdkInterfaces::timing::TimerDelegateInterface> m_timer;
227 
229  std::thread m_thread;
230 };
231 
232 template <typename Rep, typename Period, typename Task, typename... Args>
234  const std::chrono::duration<Rep, Period>& delay,
235  const std::chrono::duration<Rep, Period>& period,
236  PeriodType periodType,
237  size_t maxCount,
238  Task task,
239  Args&&... args) {
240  if (delay < std::chrono::duration<Rep, Period>::zero()) {
241  logger::acsdkError(logger::LogEntry(Timer::getTag(), "startFailed").d("reason", "negativeDelay"));
242  return false;
243  }
244  if (period < std::chrono::duration<Rep, Period>::zero()) {
245  logger::acsdkError(logger::LogEntry(Timer::getTag(), "startFailed").d("reason", "negativePeriod"));
246  return false;
247  }
248 
249  // Don't start if already running.
250  if (!activate()) {
251  logger::acsdkError(logger::LogEntry(Timer::getTag(), "startFailed").d("reason", "timerAlreadyActive"));
252  return false;
253  }
254 
255  // Remove arguments from the task's type by binding the arguments to the task.
256  using BoundTaskType = decltype(std::bind(std::forward<Task>(task), std::forward<Args>(args)...));
257  auto boundTask = std::make_shared<BoundTaskType>(std::bind(std::forward<Task>(task), std::forward<Args>(args)...));
258 
259  // Remove the return type from the task by wrapping it in a lambda with no return value.
260  auto translatedTask = [boundTask]() { boundTask->operator()(); };
261 
262  // Kick off the new timer thread.
263  callTask<Rep, Period>(delay, period, periodType, maxCount, translatedTask);
264 
265  return true;
266 }
267 
268 template <typename Rep, typename Period, typename Task, typename... Args>
270  const std::chrono::duration<Rep, Period>& period,
271  PeriodType periodType,
272  size_t maxCount,
273  Task task,
274  Args&&... args) {
275  return start(period, period, periodType, maxCount, std::forward<Task>(task), std::forward<Args>(args)...);
276 }
277 
278 template <typename Rep, typename Period, typename Task, typename... Args>
279 auto Timer::start(const std::chrono::duration<Rep, Period>& delay, Task task, Args&&... args)
280  -> std::future<decltype(task(args...))> {
281  // Don't start if already running.
282  if (!activate()) {
283  logger::acsdkError(logger::LogEntry(Timer::getTag(), "startFailed").d("reason", "timerAlreadyActive"));
284  using FutureType = decltype(task(args...));
285  return std::future<FutureType>();
286  }
287 
288  // Remove arguments from the task's type by binding the arguments to the task.
289  auto boundTask = std::bind(std::forward<Task>(task), std::forward<Args>(args)...);
290 
291  /*
292  * Create a std::packaged_task with the correct return type. The decltype only returns the return value of the
293  * boundTask. The following parentheses make it a function call with the boundTask return type. The package task
294  * will then return a future of the correct type.
295  */
296  using PackagedTaskType = std::packaged_task<decltype(boundTask())()>;
297  auto packagedTask = std::make_shared<PackagedTaskType>(boundTask);
298 
299  // Remove the return type from the task by wrapping it in a lambda with no return value.
300  auto translatedTask = [packagedTask]() { packagedTask->operator()(); };
301 
302  // Kick off the new timer thread.
303  static const size_t once = 1;
304  callTask<Rep, Period>(delay, delay, PeriodType::ABSOLUTE, once, translatedTask);
305 
306  return packagedTask->get_future();
307 }
308 
309 template <typename Rep, typename Period>
310 void Timer::callTask(
311  std::chrono::duration<Rep, Period> delay,
312  std::chrono::duration<Rep, Period> period,
313  PeriodType periodType,
314  size_t maxCount,
315  std::function<void()> task) {
316  if (!m_timer) {
317  logger::acsdkError(logger::LogEntry(Timer::getTag(), "callTaskFailed").d("reason", "nullTimerDelegate"));
318  return;
319  }
320 
322 
323  switch (periodType) {
326  break;
329  break;
330  }
331 
332  m_timer->start(
333  std::chrono::duration_cast<std::chrono::nanoseconds>(delay),
334  std::chrono::duration_cast<std::chrono::nanoseconds>(period),
335  delegatePeriodType,
336  maxCount,
337  task);
338 }
339 
340 } // namespace timing
341 } // namespace utils
342 } // namespace avsCommon
343 } // namespace alexaClientSDK
344 
345 #endif // ALEXA_CLIENT_SDK_AVSCOMMON_UTILS_INCLUDE_AVSCOMMON_UTILS_TIMING_TIMER_H_
PeriodType
Specifies different ways to apply the period of a recurring task.
Definition: Timer.h:48
static std::string getTag()
Static member function to get TAG.
Definition: Timer.h:86
bool isActive() const
Definition: Timer.cpp:63
def args
Definition: android_test.py:111
static std::shared_ptr< SDKPrimitivesProvider > getInstance()
Definition: SDKPrimitivesProvider.cpp:38
static size_t getForever()
Static member function to get FOREVER.
Definition: Timer.h:81
Whether or not curl logs should be emitted.
Definition: AVSConnectionManager.h:36
Timer(std::shared_ptr< sdkInterfaces::timing::TimerDelegateFactoryInterface > timerDelegateFactory=avs::initialization::SDKPrimitivesProvider::getInstance() ->getTimerDelegateFactory())
Definition: Timer.cpp:36
bool start(const std::chrono::duration< Rep, Period > &delay, const std::chrono::duration< Rep, Period > &period, PeriodType periodType, size_t maxCount, Task task, Args &&... args)
Definition: Timer.h:233
void acsdkError(const LogEntry &entry)
Definition: LoggerUtils.cpp:80
static const size_t FOREVER
Definition: Timer.h:45
LogEntry is used to compile the log entry text to log via Logger.
Definition: LogEntry.h:32

AlexaClientSDK 1.26.0 - Copyright 2016-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. Licensed under the Apache License, Version 2.0