00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027
00028
00029 #include <dbus-c++/eventloop-integration.h>
00030 #include <dbus-c++/debug.h>
00031 #include <dbus-c++/pipe.h>
00032
00033
00034 #include <dbus/dbus.h>
00035
00036
00037 #include <string.h>
00038 #include <cassert>
00039 #include <sys/poll.h>
00040 #include <fcntl.h>
00041
00042 using namespace DBus;
00043 using namespace std;
00044
00045 BusTimeout::BusTimeout(Timeout::Internal *ti, BusDispatcher *bd)
00046 : Timeout(ti), DefaultTimeout(Timeout::interval(), true, bd)
00047 {
00048 DefaultTimeout::enabled(Timeout::enabled());
00049 }
00050
00051 void BusTimeout::toggle()
00052 {
00053 debug_log("timeout %p toggled (%s)", this, Timeout::enabled() ? "on" : "off");
00054
00055 DefaultTimeout::enabled(Timeout::enabled());
00056 }
00057
00058 BusWatch::BusWatch(Watch::Internal *wi, BusDispatcher *bd)
00059 : Watch(wi), DefaultWatch(Watch::descriptor(), 0, bd)
00060 {
00061 int flags = POLLHUP | POLLERR;
00062
00063 if (Watch::flags() & DBUS_WATCH_READABLE)
00064 flags |= POLLIN;
00065 if (Watch::flags() & DBUS_WATCH_WRITABLE)
00066 flags |= POLLOUT;
00067
00068 DefaultWatch::flags(flags);
00069 DefaultWatch::enabled(Watch::enabled());
00070 }
00071
00072 void BusWatch::toggle()
00073 {
00074 debug_log("watch %p toggled (%s)", this, Watch::enabled() ? "on" : "off");
00075
00076 DefaultWatch::enabled(Watch::enabled());
00077 }
00078
00079 BusDispatcher::BusDispatcher() :
00080 _running(false)
00081 {
00082
00083
00084 int ret = pipe(_pipe);
00085 if (ret == -1) throw Error("PipeError:errno", toString(errno).c_str());
00086
00087 _fdunlock[0] = _pipe[0];
00088 _fdunlock[1] = _pipe[1];
00089 }
00090
00091 void BusDispatcher::enter()
00092 {
00093 debug_log("entering dispatcher %p", this);
00094
00095 _running = true;
00096
00097 while (_running)
00098 {
00099 do_iteration();
00100
00101 for (std::list <Pipe *>::iterator p_it = pipe_list.begin();
00102 p_it != pipe_list.end();
00103 ++p_it)
00104 {
00105 Pipe *read_pipe = *p_it;
00106 char buffer[1024];
00107 unsigned int nbytes = 0;
00108
00109 while (read_pipe->read(buffer, nbytes) > 0)
00110 {
00111 read_pipe->_handler(read_pipe->_data, buffer, nbytes);
00112 }
00113
00114 }
00115 }
00116
00117 debug_log("leaving dispatcher %p", this);
00118 }
00119
00120 void BusDispatcher::leave()
00121 {
00122 _running = false;
00123
00124 int ret = write(_fdunlock[1], "exit", strlen("exit"));
00125 if (ret == -1) throw Error("WriteError:errno", toString(errno).c_str());
00126
00127 close(_fdunlock[1]);
00128 close(_fdunlock[0]);
00129 }
00130
00131 Pipe *BusDispatcher::add_pipe(void(*handler)(const void *data, void *buffer, unsigned int nbyte), const void *data)
00132 {
00133 Pipe *new_pipe = new Pipe(handler, data);
00134 pipe_list.push_back(new_pipe);
00135
00136 return new_pipe;
00137 }
00138
00139 void BusDispatcher::del_pipe(Pipe *pipe)
00140 {
00141 pipe_list.remove(pipe);
00142 delete pipe;
00143 }
00144
00145 void BusDispatcher::do_iteration()
00146 {
00147 dispatch_pending();
00148 dispatch();
00149 }
00150
00151 Timeout *BusDispatcher::add_timeout(Timeout::Internal *ti)
00152 {
00153 BusTimeout *bt = new BusTimeout(ti, this);
00154
00155 bt->expired = new Callback<BusDispatcher, void, DefaultTimeout &>(this, &BusDispatcher::timeout_expired);
00156 bt->data(bt);
00157
00158 debug_log("added timeout %p (%s) (%d millies)",
00159 bt,
00160 ((Timeout *)bt)->enabled() ? "on" : "off",
00161 ((Timeout *)bt)->interval()
00162 );
00163
00164 return bt;
00165 }
00166
00167 void BusDispatcher::rem_timeout(Timeout *t)
00168 {
00169 debug_log("removed timeout %p", t);
00170
00171 delete t;
00172 }
00173
00174 Watch *BusDispatcher::add_watch(Watch::Internal *wi)
00175 {
00176 BusWatch *bw = new BusWatch(wi, this);
00177
00178 bw->ready = new Callback<BusDispatcher, void, DefaultWatch &>(this, &BusDispatcher::watch_ready);
00179 bw->data(bw);
00180
00181 debug_log("added watch %p (%s) fd=%d flags=%d",
00182 bw, ((Watch *)bw)->enabled() ? "on" : "off", ((Watch *)bw)->descriptor(), ((Watch *)bw)->flags());
00183
00184 return bw;
00185 }
00186
00187 void BusDispatcher::rem_watch(Watch *w)
00188 {
00189 debug_log("removed watch %p", w);
00190
00191 delete w;
00192 }
00193
00194 void BusDispatcher::timeout_expired(DefaultTimeout &et)
00195 {
00196 debug_log("timeout %p expired", &et);
00197
00198 BusTimeout *timeout = reinterpret_cast<BusTimeout *>(et.data());
00199
00200 timeout->handle();
00201 }
00202
00203 void BusDispatcher::watch_ready(DefaultWatch &ew)
00204 {
00205 BusWatch *watch = reinterpret_cast<BusWatch *>(ew.data());
00206
00207 debug_log("watch %p ready, flags=%d state=%d",
00208 watch, ((Watch *)watch)->flags(), watch->state()
00209 );
00210
00211 int flags = 0;
00212
00213 if (watch->state() & POLLIN)
00214 flags |= DBUS_WATCH_READABLE;
00215 if (watch->state() & POLLOUT)
00216 flags |= DBUS_WATCH_WRITABLE;
00217 if (watch->state() & POLLHUP)
00218 flags |= DBUS_WATCH_HANGUP;
00219 if (watch->state() & POLLERR)
00220 flags |= DBUS_WATCH_ERROR;
00221
00222 watch->handle(flags);
00223 }
00224