client-cpp  0.7.4
KaaTimer.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2014-2015 CyberVision, Inc.
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  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef KAATIMER_HPP_
18 #define KAATIMER_HPP_
19 
20 #include <chrono>
21 #include <mutex>
22 #include <thread>
23 #include <functional>
24 #include <condition_variable>
25 
26 #include "kaa/KaaThread.hpp"
27 #include "kaa/logging/Log.hpp"
29 
30 namespace kaa {
31 
32 template<class Signature, class Function = std::function<Signature>>
33 class KaaTimer {
34  typedef std::chrono::system_clock TimerClock;
35 public:
36  KaaTimer(const std::string& timerName) :
37  timerName_(timerName), isThreadRun_(false), isTimerRun_(false), callback_([]{})
38  {
39  }
40 
42  {
43  /*
44  * Do not add the mutex logging it may cause crashes.
45  */
46  if (isThreadRun_ && timerThread_.joinable()) {
47  std::unique_lock<std::mutex> timerLock(timerGuard_);
48 
49  isThreadRun_ = false;
50  condition_.notify_one();
51 
52  timerLock.unlock();
53 
54  timerThread_.join();
55  }
56  }
57 
58  void start(std::size_t seconds, const Function& callback)
59  {
60  if (!callback) {
61  KAA_LOG_WARN("Failed to start timer: bad callback");
62  throw KaaException("Bad timer callback");
63  }
64 
65  KAA_LOG_TRACE(boost::format("Timer[%1%] scheduling for %2% sec ...") % timerName_ % seconds );
66 
67  KAA_MUTEX_LOCKING("timerGuard_");
68  std::unique_lock<std::mutex> timerLock(timerGuard_);
69  KAA_MUTEX_LOCKED("timerGuard_");
70 
71  if (!isThreadRun_) {
72  isThreadRun_ = true;
73  timerThread_ = std::thread([&] { run(); });
74  }
75 
76  if (!isTimerRun_) {
77  endTS_ = TimerClock::now() + std::chrono::seconds(seconds);
78  isTimerRun_ = true;
79  callback_ = callback;
80  condition_.notify_one();
81  }
82  }
83 
84  void stop()
85  {
86  KAA_LOG_TRACE(boost::format("Timer[%1%] stopping ...") % timerName_);
87 
88  KAA_MUTEX_LOCKING("timerGuard_");
89  std::unique_lock<std::mutex> timerLock(timerGuard_);
90  KAA_MUTEX_LOCKED("timerGuard_");
91 
92  if (isTimerRun_) {
93  isTimerRun_ = false;
94  condition_.notify_one();
95  }
96  }
97 
98 private:
99  void run()
100  {
101  KAA_LOG_TRACE(boost::format("Timer[%1%] starting thread ...") % timerName_);
102 
103  KAA_MUTEX_LOCKING("timerGuard_");
104  std::unique_lock<std::mutex> timerLock(timerGuard_);
105  KAA_MUTEX_LOCKED("timerGuard_");
106 
107  while (isThreadRun_) {
108  if (isTimerRun_) {
109  auto now = TimerClock::now();
110  if (now >= endTS_) {
111  KAA_LOG_TRACE(boost::format("Timer[%1%] executing callback ...") % timerName_);
112  isTimerRun_ = false;
113 
114  auto currentCallback = callback_;
115 
116  KAA_MUTEX_UNLOCKING("timerGuard_");
117  timerLock.unlock();
118  KAA_MUTEX_UNLOCKED("timerGuard_");
119 
120  currentCallback();
121 
122  KAA_MUTEX_LOCKING("timer_mutex_");
123  timerLock.lock();
124  KAA_MUTEX_LOCKED("timer_mutex_");
125  } else {
126  KAA_MUTEX_UNLOCKING("timerGuard_");
127  condition_.wait_for(timerLock, (endTS_ - now));
128  KAA_MUTEX_LOCKED("timerGuard_");
129  }
130  } else {
131  KAA_MUTEX_UNLOCKING("timerGuard_");
132  condition_.wait(timerLock);
133  KAA_MUTEX_LOCKED("timerGuard_");
134  }
135  }
136  }
137 
138 private:
139  const std::string timerName_;
140 
141  bool isThreadRun_;
142  bool isTimerRun_;
143 
144  std::thread timerThread_;
145  std::condition_variable condition_;
146 
147  std::mutex timerGuard_;
148 
149  std::chrono::time_point<TimerClock> endTS_;
150 
151  Function callback_;
152 };
153 
154 } /* namespace kaa */
155 
156 #endif /* KAATIMER_HPP_ */
KaaTimer(const std::string &timerName)
Definition: KaaTimer.hpp:36
#define KAA_MUTEX_UNLOCKING(mutex_name)
Definition: Log.hpp:115
#define KAA_MUTEX_LOCKED(mutex_name)
Definition: Log.hpp:114
#define KAA_LOG_TRACE(message)
Definition: Log.hpp:54
void start(std::size_t seconds, const Function &callback)
Definition: KaaTimer.hpp:58
#define KAA_LOG_WARN(message)
Definition: Log.hpp:69
#define KAA_MUTEX_UNLOCKED(mutex_name)
Definition: Log.hpp:116
void stop()
Definition: KaaTimer.hpp:84
#define KAA_MUTEX_LOCKING(mutex_name)
Definition: Log.hpp:113