00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "wvqtstreamclone.moc"
00023
00024
00025
00026 #define NUM_SLOTS 41 // must be prime
00027
00028 WvQtStreamClone::WvQtStreamClone(WvStream* _cloned, int msec_timeout) :
00029 WvStreamClone(_cloned), msec_timeout(msec_timeout),
00030 pending_callback(false), first_time(true), select_in_progress(false),
00031 last_max_fd(-1),
00032 notify_readable(NUM_SLOTS),
00033 notify_writable(NUM_SLOTS),
00034 notify_exception(NUM_SLOTS)
00035 {
00036 notify_readable.setAutoDelete(true);
00037 notify_writable.setAutoDelete(true);
00038 notify_exception.setAutoDelete(true);
00039 qt_attach();
00040 }
00041
00042
00043 WvQtStreamClone::~WvQtStreamClone()
00044 {
00045 }
00046
00047
00048 void WvQtStreamClone::pre_poll()
00049 {
00050
00051 bool sure = _build_selectinfo(si, msec_timeout,
00052 false, false, false, true);
00053 if (sure)
00054 {
00055 pending_callback = true;
00056 si.msec_timeout = 0;
00057 }
00058
00059
00060
00061
00062 select_timer.stop();
00063 if (si.msec_timeout >= 0)
00064 select_timer.start(si.msec_timeout, true );
00065
00066
00067
00068 for (int fd = 0; fd <= si.max_fd; ++fd)
00069 {
00070 if (FD_ISSET(fd, &si.read))
00071 {
00072 QSocketNotifier *n = notify_readable.find(fd);
00073 if (! n)
00074 {
00075 n = new QSocketNotifier(fd, QSocketNotifier::Read);
00076 notify_readable.insert(fd, n);
00077 QObject::connect(n, SIGNAL(activated(int)),
00078 this, SLOT(fd_readable(int)));
00079 }
00080 } else
00081 notify_readable.remove(fd);
00082
00083 if (FD_ISSET(fd, &si.write))
00084 {
00085 QSocketNotifier *n = notify_writable.find(fd);
00086 if (! n)
00087 {
00088 n = new QSocketNotifier(fd, QSocketNotifier::Write);
00089 notify_writable.insert(fd, n);
00090 QObject::connect(n, SIGNAL(activated(int)),
00091 this, SLOT(fd_writable(int)));
00092 }
00093 } else
00094 notify_writable.remove(fd);
00095
00096 if (FD_ISSET(fd, &si.except))
00097 {
00098 QSocketNotifier *n = notify_exception.find(fd);
00099 if (! n)
00100 {
00101 n = new QSocketNotifier(fd, QSocketNotifier::Exception);
00102 notify_exception.insert(fd, n);
00103 QObject::connect(n, SIGNAL(activated(int)),
00104 this, SLOT(fd_exception(int)));
00105 }
00106 } else
00107 notify_exception.remove(fd);
00108 }
00109
00110
00111 for (int fd = si.max_fd + 1; fd <= last_max_fd; ++fd)
00112 {
00113 notify_readable.remove(fd);
00114 notify_writable.remove(fd);
00115 notify_exception.remove(fd);
00116 }
00117 last_max_fd = si.max_fd;
00118
00119
00120 FD_ZERO(&si.read);
00121 FD_ZERO(&si.write);
00122 FD_ZERO(&si.except);
00123 }
00124
00125
00126 void WvQtStreamClone::post_poll()
00127 {
00128
00129 bool sure = _process_selectinfo(si, true);
00130 if (sure || pending_callback)
00131 {
00132 pending_callback = false;
00133 callback();
00134 if (globalstream) globalstream->callback();
00135 }
00136 }
00137
00138
00139 void WvQtStreamClone::set_timeout(int msec_timeout)
00140 {
00141 this->msec_timeout = msec_timeout;
00142 }
00143
00144
00145 void WvQtStreamClone::qt_begin_event_loop_hook()
00146 {
00147
00148 if (select_in_progress) return;
00149
00150
00151 if (! first_time)
00152 post_poll();
00153 else
00154 first_time = false;
00155
00156 pre_poll();
00157 select_in_progress = true;
00158 }
00159
00160
00161 void WvQtStreamClone::qt_detach()
00162 {
00163
00164 if (! first_time)
00165 {
00166 select_in_progress = false;
00167 post_poll();
00168 last_max_fd = -1;
00169 first_time = true;
00170 }
00171
00172 select_timer.stop();
00173 notify_readable.clear();
00174 notify_writable.clear();
00175 notify_exception.clear();
00176 QObject::disconnect(qApp, SIGNAL(guiThreadAwake()),
00177 this, SLOT(qt_begin_event_loop_hook()));
00178 QObject::disconnect(& select_timer, SIGNAL(timeout()),
00179 this, SLOT(select_timer_expired()));
00180 }
00181
00182
00183 void WvQtStreamClone::qt_attach()
00184 {
00185
00186 QObject::connect(qApp, SIGNAL(guiThreadAwake()),
00187 this, SLOT(qt_begin_event_loop_hook()));
00188 QObject::connect(& select_timer, SIGNAL(timeout()),
00189 this, SLOT(select_timer_expired()));
00190 }
00191
00192
00193 void WvQtStreamClone::select_timer_expired()
00194 {
00195 select_in_progress = false;
00196 }
00197
00198
00199 void WvQtStreamClone::fd_readable(int fd)
00200 {
00201 FD_SET(fd, &si.read);
00202 pending_callback = true;
00203 select_in_progress = false;
00204 }
00205
00206
00207 void WvQtStreamClone::fd_writable(int fd)
00208 {
00209 FD_SET(fd, &si.write);
00210 pending_callback = true;
00211 select_in_progress = false;
00212 }
00213
00214
00215 void WvQtStreamClone::fd_exception(int fd)
00216 {
00217 FD_SET(fd, &si.except);
00218 pending_callback = true;
00219 select_in_progress = false;
00220 }
00221
00222 void WvQtStreamClone::execute()
00223 {
00224 WvStreamClone::execute();
00225 }