OpenSDN source code
timer.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 // Timer implementation using ASIO and Task infrastructure.
6 // Registers an ASIO timer. On ASIO timer expiry, a task will be created to
7 // run the timer. Supports user specified task-id.
8 //
9 // Operations supported
10 // - Create a timer by allocating an object of type Timer
11 // - Start a timer
12 // If a timer is already running, it is a no op. In order to auto-restart
13 // a timer, return 'tru'e from timer callback, false otherwise
14 //
15 // There can be atmost one "Task" outstanding for the timer.
16 //
17 // - Cancel a timer
18 // Cancels a running timer. Both ASIO registerations and task spawned will
19 // be cancelled.
20 //
21 // If timer is already fired, "Cancel" api will fail and return 'false'
22 //
23 // - Delete a timer
24 // Cancels the timer and triggers deletion of the timer. Application should
25 // not access the timer after its deleted
26 //
27 // Concurrency aspects:
28 // - Timer is allocated by application
29 // - Applications must call TimerManager::DeleteTimer() to delete the timer
30 // - All operations on timer are protected by mutex
31 // - When timer is running, it can have references from ASIO and Task.
32 // Timer class will keep of reference from ASIO and Task. Timer will
33 // be deleted when both the references go away. (via intrusive pointer)
34 //
35 
36 #ifndef TIMER_H_
37 #define TIMER_H_
38 
39 #include <atomic>
40 #include <mutex>
41 #include <set>
42 
43 #include <boost/asio/placeholders.hpp>
44 #include <boost/bind/bind.hpp>
45 #include <boost/intrusive_ptr.hpp>
46 #include <boost/scoped_ptr.hpp>
47 #include <boost/function.hpp>
48 #include <boost/asio.hpp>
49 #include <boost/system/error_code.hpp>
50 
51 #include <base/task.h>
52 
53 using namespace boost::placeholders;
54 
55 class TimerImpl;
56 
57 class Timer {
58 private:
59  // Task used to fire the timer
60  class TimerTask;
61 
62 public:
63  typedef boost::function<bool(void)> Handler;
64  typedef boost::function<void(std::string, std::string, std::string)>
66 
67  Timer(boost::asio::io_context &service, const std::string &name,
68  int task_id, int task_instance, bool delete_on_completion = false);
69  virtual ~Timer();
70 
71  // Start a timer
72  // If timer already started, try cancelling and restart
73  //
74  // Timer callback routine handler should return true to start the timer
75  // again, false otherwise
76  //
77  // XXX Timer cannot be Start()ed from timer callback routine itself.
78  // Return true from the callback in order to post the timer again. This
79  // would use the same time, the timer was initially started with
80  //
81  bool Start(int time, Handler handler, ErrorHandler error_handler = NULL);
82 
83  //Can be called only from callback
84  bool Reschedule(int time);
85 
86  // Cancel a running timer
87  bool Cancel();
88 
89  bool running() const {
90  std::scoped_lock lock(mutex_);
91  return (state_ == Running);
92  }
93 
94  bool fired() const {
95  std::scoped_lock lock(mutex_);
96  return (state_ == Fired);
97  }
98 
99  int time() const {
100  return time_;
101  }
102 
103  bool cancelled() const {
104  std::scoped_lock lock(mutex_);
105  return (state_ == Cancelled);
106  }
107 
108  bool Idle() const {
109  std::scoped_lock lock(mutex_);
110  return (state_ == Cancelled || state_ == Init);
111  }
112 
113  bool IsDeleteOnCompletion() const {
114  return delete_on_completion_;
115  }
116 
117  int64_t GetElapsedTime() const;
118 
119  // Only for state machine test
120  // XXX: Don't use in production code
121  void Fire() {
122  std::scoped_lock lock(mutex_);
123  if (handler_ && !handler_.empty()) {
124  SetState(Fired);
125  handler_();
126  SetState(Init);
127  }
128  }
129 
130  virtual std::string Description() {
131  return name_;
132  }
133 private:
134  friend class TimerManager;
135  friend class TimerTest;
136 
137  friend void intrusive_ptr_add_ref(Timer *timer);
138  friend void intrusive_ptr_release(Timer *timer);
139  typedef boost::intrusive_ptr<Timer> TimerPtr;
140 
141  enum TimerState {
142  Init = 0,
143  Running = 1,
144  Fired = 2,
145  Cancelled = 3,
146  };
147 
148  // ASIO callback on timer expiry. Start a task to serve the timer
149  void StartTimerTask(TimerPtr reference,
150  int time, uint32_t seq_no,
151  const boost::system::error_code &ec);
152 
153  void SetState(TimerState s) { state_ = s; }
154  static int GetTimerInstanceId() { return -1; }
155  static int GetTimerTaskId() {
156  static int timer_task_id = -1;
157 
158  if (timer_task_id == -1) {
160  timer_task_id = scheduler->GetTaskId("timer::TimerTask");
161  }
162  return timer_task_id;
163  }
164 
165  boost::scoped_ptr<TimerImpl> impl_;
166  std::string name_;
169  mutable std::mutex mutex_;
172  int time_;
173  int task_id_;
175  uint32_t seq_no_;
177  std::atomic<int> refcount_;
178 };
179 
180 inline void intrusive_ptr_add_ref(Timer *timer) {
181  timer->refcount_++;
182 }
183 
184 inline void intrusive_ptr_release(Timer *timer) {
185  int prev = timer->refcount_.fetch_sub(1);
186  if (prev == 1) {
187  delete timer;
188  }
189 }
190 
191 //
192 // TimerManager is the place holder for all the Timer objects
193 // instantiated in the life time of a process
194 //
195 // Timer objects are help in TimerSet until all the cleanup is complete
196 // and only then should they be deleted via DeleteTimer() API
197 //
198 // Since Timer objects are also held by boost::asio routines, they are
199 // protected using intrusive pointers
200 //
201 // This is similar to how TcpSession objects are managed via TcpSessionPtr
202 //
204 public:
205  static Timer *CreateTimer(boost::asio::io_context &service,
206  const std::string &name,
207  int task_id = Timer::GetTimerTaskId(),
208  int task_instance = Timer::GetTimerInstanceId(),
209  bool delete_on_completion = false);
210  static bool DeleteTimer(Timer *Timer);
211 
212 private:
213  friend class TimerTest;
214 
215  typedef boost::intrusive_ptr<Timer> TimerPtr;
216  struct TimerPtrCmp {
217  bool operator()(const TimerPtr &lhs,
218  const TimerPtr &rhs) const {
219  return lhs.get() < rhs.get();
220  }
221  };
222  typedef std::set<TimerPtr, TimerPtrCmp> TimerSet;
223  static void AddTimer(Timer *Timer);
224 
225  static std::mutex mutex_;
227 };
228 
229 #endif /* TIMER_H_ */
The TaskScheduler keeps track of what tasks are currently schedulable. When a task is enqueued it is ...
Definition: task.h:304
int GetTaskId(const std::string &name)
Definition: task.cc:861
static TaskScheduler * GetInstance()
Definition: task.cc:554
static TimerSet timer_ref_
Definition: timer.h:226
static std::mutex mutex_
Definition: timer.h:225
std::set< TimerPtr, TimerPtrCmp > TimerSet
Definition: timer.h:222
boost::intrusive_ptr< Timer > TimerPtr
Definition: timer.h:215
Definition: timer.h:57
TimerState
Definition: timer.h:141
bool IsDeleteOnCompletion() const
Definition: timer.h:113
bool Idle() const
Definition: timer.h:108
int task_id_
Definition: timer.h:173
void SetState(TimerState s)
Definition: timer.h:153
int task_instance_
Definition: timer.h:174
bool running() const
Definition: timer.h:89
uint32_t seq_no_
Definition: timer.h:175
boost::scoped_ptr< TimerImpl > impl_
Definition: timer.h:165
bool cancelled() const
Definition: timer.h:103
std::mutex mutex_
Definition: timer.h:169
TimerState state_
Definition: timer.h:170
void Fire()
Definition: timer.h:121
ErrorHandler error_handler_
Definition: timer.h:168
static int GetTimerInstanceId()
Definition: timer.h:154
boost::intrusive_ptr< Timer > TimerPtr
Definition: timer.h:139
std::string name_
Definition: timer.h:166
int time_
Definition: timer.h:172
TimerTask * timer_task_
Definition: timer.h:171
Handler handler_
Definition: timer.h:167
virtual std::string Description()
Definition: timer.h:130
boost::function< bool(void)> Handler
Definition: timer.h:60
bool delete_on_completion_
Definition: timer.h:176
boost::function< void(std::string, std::string, std::string)> ErrorHandler
Definition: timer.h:65
std::atomic< int > refcount_
Definition: timer.h:177
bool fired() const
Definition: timer.h:94
int time() const
Definition: timer.h:99
static int GetTimerTaskId()
Definition: timer.h:155
bool operator()(const TimerPtr &lhs, const TimerPtr &rhs) const
Definition: timer.h:217
void intrusive_ptr_add_ref(Timer *timer)
Definition: timer.h:180
void intrusive_ptr_release(Timer *timer)
Definition: timer.h:184