ccRTP 2.1.2
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TimeoutProvider.h
Go to the documentation of this file.
1 /*
2  Copyright (C) 2006, 2005, 2004 Erik Eliasson, Johan Bilien, Werner Dittmann
3 
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Lesser General Public
6  License as published by the Free Software Foundation; either
7  version 2.1 of the License, or (at your option) any later version.
8 
9  This library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  Lesser General Public License for more details.
13 
14  You should have received a copy of the GNU Lesser General Public
15  License along with this library; if not, write to the Free Software
16  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18 
19 
20 #ifndef TIMEOUTPROVIDER_H
21 #define TIMEOUTPROVIDER_H
22 
35 #include <list>
36 #include <sys/time.h>
37 
38 #include <commoncpp/config.h>
39 #include <commoncpp/thread.h>
40 
51 template <class TOCommand, class TOSubscriber>
52 class TPRequest
53 {
54 
55 public:
56 
57  TPRequest( TOSubscriber tsi, int timeoutMs, const TOCommand &command):
58  subscriber(tsi)
59  {
60  struct timeval tv;
61  gettimeofday(&tv, NULL );
62 
63  when_ms = ((uint64)tv.tv_sec) * (uint64)1000 + ((uint64)tv.tv_usec) / (uint64)1000;
64  when_ms += timeoutMs;
65  this->command = command;
66  }
67 
71  bool happensBefore(uint64 t)
72  {
73  if (when_ms < t) {
74  return true;
75  }
76  if (when_ms > t) {
77  return false;
78  }
79  return false; // if equal it does not "happens_before"
80 
81  }
82 
83  bool happensBefore(const TPRequest *req){
84  return happensBefore(req->when_ms);
85  }
86 
92  {
93  struct timeval tv;
94  gettimeofday(&tv, NULL );
95 
96  uint64 now = ((uint64)tv.tv_sec) * (uint64)1000 + ((uint64)tv.tv_usec) / (uint64)1000;
97 
98  if (happensBefore(now)) {
99  return 0;
100  }
101  else {
102  return (int)(when_ms - now);
103  }
104  }
105 
106  TOCommand getCommand()
107  {
108  return command;
109  }
110 
111  TOSubscriber getSubscriber()
112  {
113  return subscriber;
114  }
115 
123  {
124  if (req.subscriber == subscriber &&
125  req.command == command &&
126  req.when_ms == when_ms) {
127  return true;
128  }
129  return false;
130  }
131 
132 private:
133  TOSubscriber subscriber;
134  uint64 when_ms; // Time since Epoch in ms when the timeout
135  // will happen
136 
137  TOCommand command; // Command that will be delivered to the
138  // receiver (subscriber) of the timeout.
139 };
140 
147 template<class TOCommand, class TOSubscriber>
148  class TimeoutProvider : public ost::Thread, ost::Event {
149 
150 public:
151 
156 
161  terminate();
162  }
163 
167  void stopThread(){
168  stop = true;
169  signal(); // signal event to waiting thread
170  }
171 
183  void requestTimeout(int32_t time_ms, TOSubscriber subscriber, const TOCommand &command)
184  {
186  new TPRequest<TOCommand, TOSubscriber>(subscriber, time_ms, command);
187 
188  synchLock.enter();
189 
190  if (requests.size()==0) {
191  requests.push_front(request);
192  signal();
193  synchLock.leave();
194  return;
195  }
196  if (request->happensBefore(requests.front())) {
197  requests.push_front(request);
198  signal();
199  synchLock.leave();
200  return;
201  }
202  if (requests.back()->happensBefore(request)){
203  requests.push_back(request);
204  signal();
205  synchLock.leave();
206  return;
207  }
208 
209  typename std::list<TPRequest<TOCommand, TOSubscriber>* >::iterator i;
210  for(i = requests.begin(); i != requests.end(); i++ ) {
211  if( request->happensBefore(*i)) {
212  requests.insert(i, request);
213  break;
214  }
215  }
216  signal();
217  synchLock.leave();
218  }
219 
225  void cancelRequest(TOSubscriber subscriber, const TOCommand &command)
226  {
227  synchLock.enter();
228  typename std::list<TPRequest<TOCommand, TOSubscriber>* >::iterator i;
229  for(i = requests.begin(); i != requests.end(); ) {
230  if( (*i)->getCommand() == command &&
231  (*i)->getSubscriber() == subscriber) {
232  i = requests.erase(i);
233  continue;
234  }
235  i++;
236  }
237  synchLock.leave();
238  }
239 
240 protected:
241 
242  void run()
243  {
244  do {
245  synchLock.enter();
246  int32_t time = 3600000;
247  int32_t size = 0;
248  if ((size = requests.size()) > 0) {
249  time = requests.front()->getMsToTimeout();
250  }
251  if (time == 0 && size > 0) {
252  if (stop){ // This must be checked so that we will
253  // stop even if we have timeouts to deliver.
254  synchLock.leave();
255  return;
256  }
258  TOSubscriber subs = req->getSubscriber();
259  TOCommand command = req->getCommand();
260 
261  requests.pop_front();
262 
263  synchLock.leave(); // call the command with free Mutex
264  subs->handleTimeout(command);
265  continue;
266  }
267  synchLock.leave();
268  if (stop) { // If we were told to stop while delivering
269  // a timeout we will exit here
270  return;
271  }
272  reset(); // ready to receive triggers again
273  wait(time);
274  if (stop) { // If we are told to exit while waiting we
275  // will exit
276  return;
277  }
278  } while(true);
279  }
280 
281 private:
282 
283  // The timeouts are ordered in the order of which they
284  // will expire. Nearest in future is first in list.
285  std::list<TPRequest<TOCommand, TOSubscriber> *> requests;
286 
287  ost::Mutex synchLock; // Protects the internal data structures
288 
289  bool stop; // Flag to tell the worker thread
290  // to terminate. Set to true and
291  // wake the worker thread to
292  // terminate it.
293 };
294 
295 #endif
296 
TPRequest(TOSubscriber tsi, int timeoutMs, const TOCommand &command)
Provides a way to request timeouts after a number of milli seconds.
void requestTimeout(int32_t time_ms, TOSubscriber subscriber, const TOCommand &command)
Request a timeout trigger.
Class to generate objects giving timeout functionality.
TOSubscriber subscriber
bool happensBefore(const TPRequest *req)
TOSubscriber getSubscriber()
TOCommand command
void stopThread()
Terminates the Timeout provider thread.
std::list< TPRequest< TOCommand, TOSubscriber > * > requests
TimeoutProvider()
Timeout Provide Constructor.
bool operator==(const TPRequest< TOCommand, TOSubscriber > &req)
Two timeout requests are considered equeal if they have the same subscriber AND command AND time when...
int getMsToTimeout()
Number of milli seconds until timeout from when this method is called.
TOCommand getCommand()
uint64 when_ms
bool happensBefore(uint64 t)
void cancelRequest(TOSubscriber subscriber, const TOCommand &command)
Removes timeout requests that belong to a subscriber and command.
~TimeoutProvider()
Destructor also terminates the Timeout thread.
ost::Mutex synchLock