Imported Upstream version 3.0
[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 2, 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
31 #ifdef HAVE_SELECT
32 #  ifdef HAVE_SYS_SELECT_H
33 #    include <sys/select.h>
34 #  else
35 #    ifdef HAVE_SYS_TIME_H
36 #      include <sys/time.h>
37 #    endif
38 #    ifdef HAVE_SYS_TYPES_H
39 #      include <sys/types.h>
40 #    endif
41 #    ifdef HAVE_UNISTD_H
42 #      include <unistd.h>
43 #    endif
44 #  endif
45 #endif
46
47
48 static gr_dispatcher_sptr s_singleton;
49
50 gr_dispatcher_sptr
51 gr_make_dispatcher()
52 {
53   return gr_dispatcher_sptr(new gr_dispatcher());
54 }
55
56 gr_dispatcher_sptr
57 gr_dispatcher_singleton()
58 {
59   if (s_singleton)
60     return s_singleton;
61
62   s_singleton = gr_make_dispatcher();
63   return s_singleton;
64 }
65
66 #if !defined(HAVE_SELECT)               // Stub it out
67
68 gr_dispatcher::gr_dispatcher()
69 {
70 }
71
72 gr_dispatcher::~gr_dispatcher()
73 {
74 }
75
76 bool
77 gr_dispatcher::add_handler(gr_select_handler_sptr handler)
78 {
79   return true;
80 }
81
82 bool
83 gr_dispatcher::del_handler(gr_select_handler_sptr handler)
84 {
85   return true;
86 }
87
88 bool
89 gr_dispatcher::del_handler(gr_select_handler *handler)
90 {
91   return true;
92 }
93
94 void
95 gr_dispatcher::loop(double timeout)
96 {
97 }
98
99 #else                   // defined(HAVE_SELECT)
100
101 gr_dispatcher::gr_dispatcher()
102   : d_handler(FD_SETSIZE), d_max_index(-1)
103 {
104 }
105
106 gr_dispatcher::~gr_dispatcher()
107 {
108 }
109
110 bool
111 gr_dispatcher::add_handler(gr_select_handler_sptr handler)
112 {
113   int fd = handler->fd();
114   if (fd < 0 || fd >= FD_SETSIZE)
115     return false;
116
117   d_max_index = std::max(d_max_index, fd);
118   d_handler[fd] = handler;
119   return true;
120 }
121
122 bool
123 gr_dispatcher::del_handler(gr_select_handler_sptr handler)
124 {
125   return del_handler(handler.get());
126 }
127
128 bool
129 gr_dispatcher::del_handler(gr_select_handler *handler)
130 {
131   int fd = handler->fd();
132   if (fd < 0 || fd >= FD_SETSIZE)
133     return false;
134
135   d_handler[fd].reset();
136
137   if (fd == d_max_index){
138     int i;
139     for (i = fd - 1; i >= 0 && !d_handler[i]; i--)
140       ;
141     d_max_index = i;
142   }
143   return true;
144 }
145
146
147 void
148 gr_dispatcher::loop(double timeout)
149 {
150   struct timeval master;
151   struct timeval tmp;
152   fd_set         rd_set;
153   fd_set         wr_set;
154
155   double secs = floor (timeout);
156   master.tv_sec = (long) secs;
157   master.tv_usec = (long) ((timeout - secs) * 1e6);
158
159   while (d_max_index >= 0){
160     FD_ZERO(&rd_set);
161     FD_ZERO(&wr_set);
162
163     for (int i = 0; i <= d_max_index; i++){
164       if (d_handler[i] && d_handler[i]->readable())
165         FD_SET(i, &rd_set);
166       if (d_handler[i] && d_handler[i]->writable())
167         FD_SET(i, &wr_set);
168     }
169
170     tmp = master;
171     int retval = select(d_max_index+1, &rd_set, &wr_set, 0, &tmp);
172     if (retval == 0)    // timed out with nothing ready
173       continue;
174     if (retval < 0){
175       if (errno == EINTR)
176         continue;
177       perror ("gr_dispatcher/select");
178       return;
179     }
180
181     for (int i = 0; i <= d_max_index; i++){
182       if (FD_ISSET(i, &rd_set))
183         if (d_handler[i])
184           d_handler[i]->handle_read();
185       if (FD_ISSET(i, &wr_set))
186         if (d_handler[i])
187           d_handler[i]->handle_write();
188     }
189   }
190 }
191
192 #endif