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(IWvStream *_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 setclone(_cloned);
00037 disassociate_on_close = true;
00038 notify_readable.setAutoDelete(true);
00039 notify_writable.setAutoDelete(true);
00040 notify_exception.setAutoDelete(true);
00041 qt_attach();
00042 }
00043
00044
00045 WvQtStreamClone::~WvQtStreamClone()
00046 {
00047 }
00048
00049
00050 void WvQtStreamClone::pre_poll()
00051 {
00052
00053 bool sure = _build_selectinfo(si, msec_timeout,
00054 false, false, false, true);
00055 if (sure)
00056 {
00057 pending_callback = true;
00058 si.msec_timeout = 0;
00059 }
00060
00061
00062
00063
00064 select_timer.stop();
00065 if (si.msec_timeout >= 0)
00066 select_timer.start(si.msec_timeout, true );
00067
00068
00069
00070 for (int fd = 0; fd <= si.max_fd; ++fd)
00071 {
00072 if (FD_ISSET(fd, &si.read))
00073 {
00074 QSocketNotifier *n = notify_readable.find(fd);
00075 if (! n)
00076 {
00077 n = new QSocketNotifier(fd, QSocketNotifier::Read);
00078 notify_readable.insert(fd, n);
00079 QObject::connect(n, SIGNAL(activated(int)),
00080 this, SLOT(fd_readable(int)));
00081 }
00082 } else
00083 notify_readable.remove(fd);
00084
00085 if (FD_ISSET(fd, &si.write))
00086 {
00087 QSocketNotifier *n = notify_writable.find(fd);
00088 if (! n)
00089 {
00090 n = new QSocketNotifier(fd, QSocketNotifier::Write);
00091 notify_writable.insert(fd, n);
00092 QObject::connect(n, SIGNAL(activated(int)),
00093 this, SLOT(fd_writable(int)));
00094 }
00095 } else
00096 notify_writable.remove(fd);
00097
00098 if (FD_ISSET(fd, &si.except))
00099 {
00100 QSocketNotifier *n = notify_exception.find(fd);
00101 if (! n)
00102 {
00103 n = new QSocketNotifier(fd, QSocketNotifier::Exception);
00104 notify_exception.insert(fd, n);
00105 QObject::connect(n, SIGNAL(activated(int)),
00106 this, SLOT(fd_exception(int)));
00107 }
00108 } else
00109 notify_exception.remove(fd);
00110 }
00111
00112
00113 for (int fd = si.max_fd + 1; fd <= last_max_fd; ++fd)
00114 {
00115 notify_readable.remove(fd);
00116 notify_writable.remove(fd);
00117 notify_exception.remove(fd);
00118 }
00119 last_max_fd = si.max_fd;
00120
00121
00122 FD_ZERO(&si.read);
00123 FD_ZERO(&si.write);
00124 FD_ZERO(&si.except);
00125 }
00126
00127
00128 void WvQtStreamClone::post_poll()
00129 {
00130
00131 bool sure = _process_selectinfo(si, true);
00132 if (sure || pending_callback)
00133 {
00134 pending_callback = false;
00135 callback();
00136 if (globalstream) globalstream->callback();
00137 }
00138 }
00139
00140
00141 void WvQtStreamClone::set_timeout(int msec_timeout)
00142 {
00143 this->msec_timeout = msec_timeout;
00144 }
00145
00146
00147 void WvQtStreamClone::qt_begin_event_loop_hook()
00148 {
00149
00150 if (select_in_progress) return;
00151
00152
00153 if (! first_time)
00154 post_poll();
00155 else
00156 first_time = false;
00157
00158 pre_poll();
00159 select_in_progress = true;
00160 }
00161
00162
00163 void WvQtStreamClone::qt_detach()
00164 {
00165
00166 if (! first_time)
00167 {
00168 select_in_progress = false;
00169 post_poll();
00170 last_max_fd = -1;
00171 first_time = true;
00172 }
00173
00174 select_timer.stop();
00175 notify_readable.clear();
00176 notify_writable.clear();
00177 notify_exception.clear();
00178 QObject::disconnect(qApp, SIGNAL(guiThreadAwake()),
00179 this, SLOT(qt_begin_event_loop_hook()));
00180 QObject::disconnect(& select_timer, SIGNAL(timeout()),
00181 this, SLOT(select_timer_expired()));
00182 }
00183
00184
00185 void WvQtStreamClone::qt_attach()
00186 {
00187
00188 QObject::connect(qApp, SIGNAL(guiThreadAwake()),
00189 this, SLOT(qt_begin_event_loop_hook()));
00190 QObject::connect(& select_timer, SIGNAL(timeout()),
00191 this, SLOT(select_timer_expired()));
00192 }
00193
00194
00195 void WvQtStreamClone::select_timer_expired()
00196 {
00197 select_in_progress = false;
00198 }
00199
00200
00201 void WvQtStreamClone::fd_readable(int fd)
00202 {
00203 FD_SET(fd, &si.read);
00204 pending_callback = true;
00205 select_in_progress = false;
00206 }
00207
00208
00209 void WvQtStreamClone::fd_writable(int fd)
00210 {
00211 FD_SET(fd, &si.write);
00212 pending_callback = true;
00213 select_in_progress = false;
00214 }
00215
00216
00217 void WvQtStreamClone::fd_exception(int fd)
00218 {
00219 FD_SET(fd, &si.except);
00220 pending_callback = true;
00221 select_in_progress = false;
00222 }
00223
00224 void WvQtStreamClone::execute()
00225 {
00226 WvStreamClone::execute();
00227 }
00228
00229
00230 void WvQtStreamClone::setclone(IWvStream *newclone)
00231 {
00232 WvStreamClone::setclone(newclone);
00233
00234 if (newclone != NULL)
00235 my_type = WvString("WvQtStreamClone:%s", newclone->wstype());
00236 else
00237 my_type = "WvQtStreamClone:(none)";
00238 }