Imported Upstream version 3.2.2
[debian/gnuradio] / gnuradio-core / src / lib / runtime / gr_dispatcher.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2005 Free Software Foundation, Inc.
4  * 
5  * This file is part of GNU Radio
6  * 
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  * 
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with GNU Radio; see the file COPYING.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <gr_dispatcher.h>
28 #include <math.h>
29 #include <errno.h>
30 #include <stdio.h>
31
32 #ifdef HAVE_SELECT
33 #  ifdef HAVE_SYS_SELECT_H
34 #    include <sys/select.h>
35 #  else
36 #    ifdef HAVE_SYS_TIME_H
37 #      include <sys/time.h>
38 #    endif
39 #    ifdef HAVE_SYS_TYPES_H
40 #      include <sys/types.h>
41 #    endif
42 #    ifdef HAVE_UNISTD_H
43 #      include <unistd.h>
44 #    endif
45 #  endif
46 #endif
47
48
49 static gr_dispatcher_sptr s_singleton;
50
51 gr_dispatcher_sptr
52 gr_make_dispatcher()
53 {
54   return gr_dispatcher_sptr(new gr_dispatcher());
55 }
56
57 gr_dispatcher_sptr
58 gr_dispatcher_singleton()
59 {
60   if (s_singleton)
61     return s_singleton;
62
63   s_singleton = gr_make_dispatcher();
64   return s_singleton;
65 }
66
67 #if !defined(HAVE_SELECT)               // Stub it out
68
69 gr_dispatcher::gr_dispatcher()
70 {
71 }
72
73 gr_dispatcher::~gr_dispatcher()
74 {
75 }
76
77 bool
78 gr_dispatcher::add_handler(gr_select_handler_sptr handler)
79 {
80   return true;
81 }
82
83 bool
84 gr_dispatcher::del_handler(gr_select_handler_sptr handler)
85 {
86   return true;
87 }
88
89 bool
90 gr_dispatcher::del_handler(gr_select_handler *handler)
91 {
92   return true;
93 }
94
95 void
96 gr_dispatcher::loop(double timeout)
97 {
98 }
99
100 #else                   // defined(HAVE_SELECT)
101
102 gr_dispatcher::gr_dispatcher()
103   : d_handler(FD_SETSIZE), d_max_index(-1)
104 {
105 }
106
107 gr_dispatcher::~gr_dispatcher()
108 {
109 }
110
111 bool
112 gr_dispatcher::add_handler(gr_select_handler_sptr handler)
113 {
114   int fd = handler->fd();
115   if (fd < 0 || fd >= FD_SETSIZE)
116     return false;
117
118   d_max_index = std::max(d_max_index, fd);
119   d_handler[fd] = handler;
120   return true;
121 }
122
123 bool
124 gr_dispatcher::del_handler(gr_select_handler_sptr handler)
125 {
126   return del_handler(handler.get());
127 }
128
129 bool
130 gr_dispatcher::del_handler(gr_select_handler *handler)
131 {
132   int fd = handler->fd();
133   if (fd < 0 || fd >= FD_SETSIZE)
134     return false;
135
136   d_handler[fd].reset();
137
138   if (fd == d_max_index){
139     int i;
140     for (i = fd - 1; i >= 0 && !d_handler[i]; i--)
141       ;
142     d_max_index = i;
143   }
144   return true;
145 }
146
147
148 void
149 gr_dispatcher::loop(double timeout)
150 {
151   struct timeval master;
152   struct timeval tmp;
153   fd_set         rd_set;
154   fd_set         wr_set;
155
156   double secs = floor (timeout);
157   master.tv_sec = (long) secs;
158   master.tv_usec = (long) ((timeout - secs) * 1e6);
159
160   while (d_max_index >= 0){
161     FD_ZERO(&rd_set);
162     FD_ZERO(&wr_set);
163
164     for (int i = 0; i <= d_max_index; i++){
165       if (d_handler[i] && d_handler[i]->readable())
166         FD_SET(i, &rd_set);
167       if (d_handler[i] && d_handler[i]->writable())
168         FD_SET(i, &wr_set);
169     }
170
171     tmp = master;
172     int retval = select(d_max_index+1, &rd_set, &wr_set, 0, &tmp);
173     if (retval == 0)    // timed out with nothing ready
174       continue;
175     if (retval < 0){
176       if (errno == EINTR)
177         continue;
178       perror ("gr_dispatcher/select");
179       return;
180     }
181
182     for (int i = 0; i <= d_max_index; i++){
183       if (FD_ISSET(i, &rd_set))
184         if (d_handler[i])
185           d_handler[i]->handle_read();
186       if (FD_ISSET(i, &wr_set))
187         if (d_handler[i])
188           d_handler[i]->handle_write();
189     }
190   }
191 }
192
193 #endif