client-cpp  0.9.0
KaaTimer.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2014-2016 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  throw KaaException("Bad timer callback");
62  }
63  std::unique_lock<std::mutex> timerLock(timerGuard_);
64 
65  if (!isThreadRun_) {
66  isThreadRun_ = true;
67  timerThread_ = std::thread([&] { run(); });
68  }
69 
70  if (!isTimerRun_) {
71  endTS_ = TimerClock::now() + std::chrono::seconds(seconds);
72  isTimerRun_ = true;
73  callback_ = callback;
74  condition_.notify_one();
75  }
76  }
77 
78  void stop()
79  {
80  std::unique_lock<std::mutex> timerLock(timerGuard_);
81 
82  if (isTimerRun_) {
83  isTimerRun_ = false;
84  condition_.notify_one();
85  }
86  }
87 
88 private:
89  void run()
90  {
91  std::unique_lock<std::mutex> timerLock(timerGuard_);
92 
93  while (isThreadRun_) {
94  if (isTimerRun_) {
95  auto now = TimerClock::now();
96  if (now >= endTS_) {
97  isTimerRun_ = false;
98 
99  auto currentCallback = callback_;
100 
101  timerLock.unlock();
102 
103  currentCallback();
104 
105  timerLock.lock();
106  } else {
107  condition_.wait_for(timerLock, (endTS_ - now));
108  }
109  } else {
110  condition_.wait(timerLock);
111  }
112  }
113  }
114 
115 private:
116  const std::string timerName_;
117 
118  bool isThreadRun_;
119  bool isTimerRun_;
120 
121  std::thread timerThread_;
122  std::condition_variable condition_;
123 
124  std::mutex timerGuard_;
125 
126  std::chrono::time_point<TimerClock> endTS_;
127 
128  Function callback_;
129 };
130 
131 } /* namespace kaa */
132 
133 #endif /* KAATIMER_HPP_ */
KaaTimer(const std::string &timerName)
Definition: KaaTimer.hpp:36
void start(std::size_t seconds, const Function &callback)
Definition: KaaTimer.hpp:58
void stop()
Definition: KaaTimer.hpp:78