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