General IRI utilities
eventserver.cpp
1 // Copyright (C) 2009-2010 Institut de Robòtica i Informàtica Industrial, CSIC-UPC.
2 // Author Sergi Hernandez (shernand@iri.upc.edu)
3 // All rights reserved.
4 //
5 // This file is part of iriutils
6 // iriutils is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU Lesser General Public License as published by
8 // the Free Software Foundation, either version 3 of the License, or
9 // at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public License
17 // along with this program. If not, see <http://www.gnu.org/licenses/>.
18 
19 #include <math.h>
20 #include <sys/select.h>
21 #include "ctime.h"
22 #include "eventserver.h"
23 #include "eventexceptions.h"
24 #include <errno.h>
25 
26 CEventServer *CEventServer::pinstance=NULL;
27 
29 {
30 }
31 
33 {
34 }
35 
37 {
38  return *this->pinstance;
39 }
40 
41 std::list<CEvent>::iterator CEventServer::search_event(const std::string& event_id)
42 {
43  std::string id;
44  std::list<CEvent>::iterator it;
45 
46  if(event_id.size()==0)
47  {
48  /* handle exceptions */
49  throw CEventServerException(_HERE_,"Invalid event id","empty string");
50  }
51  else
52  {
53  for(it=this->event_list.begin();it!=this->event_list.end();it++)
54  {
55  id=it->get_id();
56  if(event_id==id)
57  return it;
58  }
59  return (std::list<CEvent>::iterator)NULL;
60  }
61  return (std::list<CEvent>::iterator)NULL;
62 }
63 
65 {
66  if (CEventServer::pinstance == NULL)
67  {
68  CEventServer::pinstance = new CEventServer(); // Creamos la instancia
69  }
70  return CEventServer::pinstance; // Retornamos la dirección de la instancia
71 }
72 
73 void CEventServer::create_event(const std::string& event_id)
74 {
75  CEvent *new_event;
76  std::list<CEvent>::iterator old_event;
77 
78  this->access_events.enter();
79  if((old_event=this->search_event(event_id))==(std::list<CEvent>::iterator)NULL)
80  {
81  new_event=new CEvent(event_id);
82  this->event_list.push_back(*new_event);
83  this->access_events.exit();
84  }
85  else
86  {
87  this->access_events.exit();
88  /* handle exceptions */
89  throw CEventServerException(_HERE_,"Event already exists!",event_id);
90  }
91 }
92 
93 void CEventServer::delete_event(const std::string& event_id)
94 {
95  std::list<CEvent>::iterator old_event;
96 
97  this->access_events.enter();
98  if((old_event=this->search_event(event_id))==(std::list<CEvent>::iterator)NULL)
99  {
100  this->access_events.exit();
101  /* handle exceptions */
102  throw CEventServerException(_HERE_,"Unknown event",event_id);
103  }
104  else
105  {
106  this->event_list.erase(old_event);
107  this->access_events.exit();
108  }
109 }
110 
111 void CEventServer::set_event(const std::string& event_id)
112 {
113  std::list<CEvent>::iterator event;
114 
115  this->access_events.enter();
116  if((event=this->search_event(event_id))==(std::list<CEvent>::iterator)NULL)
117  {
118  this->access_events.exit();
119  /* handle exceptions */
120  throw CEventServerException(_HERE_,"Unknown event",event_id);
121  }
122  else
123  {
124  this->access_events.exit();
125  event->set();
126  }
127 }
128 
129 void CEventServer::reset_event(const std::string& event_id)
130 {
131  std::list<CEvent>::iterator event;
132 
133  this->access_events.enter();
134  if((event=this->search_event(event_id))==(std::list<CEvent>::iterator)NULL)
135  {
136  this->access_events.exit();
137  /* handle exceptions */
138  throw CEventServerException(_HERE_,"Unknown event",event_id);
139  }
140  else
141  {
142  this->access_events.exit();
143  event->reset();
144  }
145 }
146 
147 bool CEventServer::event_is_set(const std::string& event_id)
148 {
149  std::list<CEvent>::iterator event;
150 
151  this->access_events.enter();
152  if((event=this->search_event(event_id))==(std::list<CEvent>::iterator)NULL)
153  {
154  this->access_events.exit();
155  /* handle exceptions */
156  throw CEventServerException(_HERE_,"Unknown event",event_id);
157  }
158  else
159  {
160  this->access_events.exit();
161  return event->is_set();
162  }
163 }
164 
166 {
167  size_t num;
168 
169  this->access_events.enter();
170  num=this->event_list.size();
171  this->access_events.exit();
172 
173  return (int)num;
174 }
175 
176 int CEventServer::get_num_activations(const std::string& event_id)
177 {
178  std::list<CEvent>::iterator event;
179 
180  this->access_events.enter();
181  if((event=this->search_event(event_id))==(std::list<CEvent>::iterator)NULL)
182  {
183  this->access_events.exit();
184  /* handle exceptions */
185  throw CEventServerException(_HERE_,"Unknown event",event_id);
186  }
187  else
188  {
189  this->access_events.exit();
190  return event->get_num_activations();
191  }
192 }
193 
194 int CEventServer::wait_first(std::list<std::string> events,int timeout)
195 {
196  std::list<std::string>::iterator it;
197  std::list<CEvent>::iterator event;
198  std::string event_list="";
199  int error,max_fd=0,pos=-1;
200  fd_set wait_set;
201  CTime time_out;
202  bool end=false;
203  timeval time;
204 
205  if(timeout>=0)
206  {
207  time_out.set(timeout);
208  time=time_out.getTimeInTimeval();
209  }
210  this->access_events.enter();
211  while(!end)
212  {
213  FD_ZERO(&wait_set);
214  for(it=events.begin();it!=events.end();it++)
215  {
216  if ((event=this->search_event(*it)) == (std::list<CEvent>::iterator)NULL)
217  {
218  this->access_events.exit();
219  /* handle exceptions */
220  throw CEventServerException(_HERE_,"Unknown event",*it);
221  }
222  else
223  {
224  FD_SET(event->get_fd(),&wait_set);
225  if(event->get_fd()>max_fd)
226  max_fd=event->get_fd();
227  if(it!=events.begin())
228  event_list+=",";
229  event_list+=*it;
230  }
231  }
232 
233  this->access_events.exit();
234  if(timeout>=0)
235  error=select(max_fd+1,&wait_set,NULL,NULL,&time);
236  else
237  error=select(max_fd+1,&wait_set,NULL,NULL,NULL);
238  if(error==-1)
239  {
240  if(errno!=EINTR)
241  {
242  /* handle exceptions */
243  throw CEventServerException(_HERE_,"Unexpected error while waiting the activation of one the events",event_list);
244  }
245  }
246  else if(error==0)
247  {
248  /* handle exceptions */
249  throw CEventTimeoutException(event_list);
250  }
251  else
252  {
253  this->access_events.enter();
254  for(it=events.begin();it!=events.end();it++)
255  {
256  pos++;
257  if((event=this->search_event(*it))==(std::list<CEvent>::iterator)NULL)
258  {
259  this->access_events.exit();
260  /* handle exceptions */
261  throw CEventServerException(_HERE_,"Unknown event",*it);
262  }
263  else
264  {
265  if(FD_ISSET(event->get_fd(),&wait_set))
266  {
267  if(event->is_set())
268  {
269  event->reset();
270  this->access_events.exit();
271  return pos;
272  }
273  }
274  }
275  }
276  }
277  }
278  this->access_events.exit();
279 
280  return -1;
281 }
282 
283 void CEventServer::wait_all(std::list<std::string> events,int timeout)
284 {
285  std::list<std::string>::iterator it;
286  std::list<CEvent>::iterator event;
287  std::string event_list;
288  int error,max_fd=0;
289  fd_set wait_set;
290  bool end=false;
291  CTime time_out;
292  timeval time;
293 
294  if(timeout>=0)
295  {
296  time_out.set(timeout);
297  time=time_out.getTimeInTimeval();
298  }
299  this->access_events.enter();
300  while(!end)
301  {
302  event_list="";
303  FD_ZERO(&wait_set);
304  for(it=events.begin();it!=events.end();it++)
305  {
306  if((event=this->search_event(*it))==(std::list<CEvent>::iterator)NULL)
307  {
308  this->access_events.exit();
309  /* handle exceptions */
310  throw CEventServerException(_HERE_,"Unknown event",*it);
311  }
312  else
313  {
314  FD_SET(event->get_fd(),&wait_set);
315  if(event->get_fd()>max_fd)
316  max_fd=event->get_fd();
317  if(it!=events.begin())
318  event_list+=",";
319  event_list+=*it;
320  }
321  }
322  this->access_events.exit();
323  if(timeout>=0)
324  error=select(max_fd+1,&wait_set,NULL,NULL,&time);
325  else
326  error=select(max_fd+1,&wait_set,NULL,NULL,NULL);
327  if(error==-1)
328  {
329  if(errno!=EINTR)
330  {
331  /* handle exceptions */
332  throw CEventServerException(_HERE_,"Unexpected error while waiting the activation of one the events",event_list);
333  }
334  }
335  else if(error==0)
336  {
337  /* handle exceptions */
338  throw CEventTimeoutException(event_list);
339  }
340  else
341  {
342  this->access_events.enter();
343  for(it=events.begin();it!=events.end();it++)
344  {
345  if((event=this->search_event(*it))==(std::list<CEvent>::iterator)NULL)
346  {
347  this->access_events.exit();
348  /* handle exceptions */
349  throw CEventServerException(_HERE_,"Unknown event",*it);
350  }
351  else
352  {
353  if(FD_ISSET(event->get_fd(),&wait_set))
354  {
355  if(event->is_set())
356  {
357  event->reset();
358  it=events.erase(it);
359  if(events.size()==0)
360  end=true;
361  else
362  {
363  if(timeout>=0)
364  time=time_out.getTimeInTimeval();
365  }
366  }
367  }
368  }
369  }
370  }
371  }
372  this->access_events.exit();
373 }
Implementation of a logical event.
Definition: event.h:65
void create_event(const std::string &event_id)
Function to create a new event.
Definition: eventserver.cpp:73
int get_num_activations(const std::string &event_id)
Function to get the number of activations of a single event.
Global event server.
Definition: eventserver.h:57
void wait_all(std::list< std::string > events, int timeout=-1)
Function to wait for all the events is a set.
bool event_is_set(const std::string &event_id)
Function to query if the event is active or not.
Event timeout exception class.
CEventServer & operator=(const CEventServer &object)
assign operator overloading
Definition: eventserver.cpp:36
std::list< CEvent >::iterator search_event(const std::string &event_id)
Function to search for an specific event.
Definition: eventserver.cpp:41
int get_num_events(void)
function to get the number of event
Event server exception class.
int wait_first(std::list< std::string > events, int timeout=-1)
Function to wait for the first event in a set.
timeval getTimeInTimeval(void)
Get time in a timeval strcuture.
Definition: ctime.cpp:92
Implementation of a time class and operations.
Definition: ctime.h:75
void delete_event(const std::string &event_id)
Function to delete an existing event.
Definition: eventserver.cpp:93
void exit(void)
function to release the critical section
Definition: mutex.cpp:64
void enter(void)
function to request access to the critical section
Definition: mutex.cpp:35
void set_event(const std::string &event_id)
Function to activate an event.
void set(double milliseconds=-1.0)
Sets the internal time.
Definition: ctime.cpp:110
CEventServer()
Default constructor.
Definition: eventserver.cpp:28
static CEventServer * instance(void)
Function to get a reference to the unique instance.
Definition: eventserver.cpp:64
void reset_event(const std::string &event_id)
Function to deactivate an event.