eventloop-integration.cpp
Go to the documentation of this file.
1/*
2 *
3 * D-Bus++ - C++ bindings for D-Bus
4 *
5 * Copyright (C) 2005-2007 Paolo Durante <shackan@gmail.com>
6 *
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23
24#ifdef HAVE_CONFIG_H
25#include <config.h>
26#endif
27
28/* Project */
30#include <dbus-c++/debug.h>
31#include <dbus-c++/pipe.h>
32
33/* DBus */
34#include <dbus/dbus.h>
35
36/* STD */
37#include <unistd.h>
38#include <string.h>
39#include <cassert>
40#include <sys/poll.h>
41#include <fcntl.h>
42
43using namespace DBus;
44using namespace std;
45
46BusTimeout::BusTimeout(Timeout::Internal *ti, BusDispatcher *bd)
47 : Timeout(ti), DefaultTimeout(Timeout::interval(), true, bd)
48{
50}
51
53{
54 debug_log("timeout %p toggled (%s)", this, Timeout::enabled() ? "on" : "off");
55
57}
58
59BusWatch::BusWatch(Watch::Internal *wi, BusDispatcher *bd)
60 : Watch(wi), DefaultWatch(Watch::descriptor(), 0, bd)
61{
62 int flags = POLLHUP | POLLERR;
63
64 if (Watch::flags() & DBUS_WATCH_READABLE)
65 flags |= POLLIN;
66 if (Watch::flags() & DBUS_WATCH_WRITABLE)
67 flags |= POLLOUT;
68
71}
72
74{
75 debug_log("watch %p toggled (%s)", this, Watch::enabled() ? "on" : "off");
76
78}
79
81 _running(false)
82{
83 // pipe to create a new fd used to unlock a dispatcher at any
84 // moment (used by leave function)
85 int ret = pipe(_pipe);
86 if (ret == -1) throw Error("PipeError:errno", toString(errno).c_str());
87
88 _fdunlock[0] = _pipe[0];
89 _fdunlock[1] = _pipe[1];
90}
91
93{
94 debug_log("entering dispatcher %p", this);
95
96 _running = true;
97
98 while (_running)
99 {
100 do_iteration();
101
102 for (std::list <Pipe *>::iterator p_it = pipe_list.begin();
103 p_it != pipe_list.end();
104 ++p_it)
105 {
106 Pipe *read_pipe = *p_it;
107 char buffer[1024]; // TODO: should be max pipe size
108 unsigned int nbytes = 0;
109
110 while (read_pipe->read(buffer, nbytes) > 0)
111 {
112 read_pipe->_handler(read_pipe->_data, buffer, nbytes);
113 }
114
115 }
116 }
117
118 debug_log("leaving dispatcher %p", this);
119}
120
122{
123 _running = false;
124
125 int ret = write(_fdunlock[1], "exit", strlen("exit"));
126 if (ret == -1) throw Error("WriteError:errno", toString(errno).c_str());
127
128 close(_fdunlock[1]);
129 close(_fdunlock[0]);
130}
131
132Pipe *BusDispatcher::add_pipe(void(*handler)(const void *data, void *buffer, unsigned int nbyte), const void *data)
133{
134 Pipe *new_pipe = new Pipe(handler, data);
135 pipe_list.push_back(new_pipe);
136
137 return new_pipe;
138}
139
141{
142 pipe_list.remove(pipe);
143 delete pipe;
144}
145
151
152Timeout *BusDispatcher::add_timeout(Timeout::Internal *ti)
153{
154 BusTimeout *bt = new BusTimeout(ti, this);
155
157 bt->data(bt);
158
159 debug_log("added timeout %p (%s) (%d millies)",
160 bt,
161 ((Timeout *)bt)->enabled() ? "on" : "off",
162 ((Timeout *)bt)->interval()
163 );
164
165 return bt;
166}
167
169{
170 debug_log("removed timeout %p", t);
171
172 delete t;
173}
174
175Watch *BusDispatcher::add_watch(Watch::Internal *wi)
176{
177 BusWatch *bw = new BusWatch(wi, this);
178
180 bw->data(bw);
181
182 debug_log("added watch %p (%s) fd=%d flags=%d",
183 bw, ((Watch *)bw)->enabled() ? "on" : "off", ((Watch *)bw)->descriptor(), ((Watch *)bw)->flags());
184
185 return bw;
186}
187
189{
190 debug_log("removed watch %p", w);
191
192 delete w;
193}
194
196{
197 debug_log("timeout %p expired", &et);
198
199 BusTimeout *timeout = reinterpret_cast<BusTimeout *>(et.data());
200
201 timeout->handle();
202}
203
205{
206 BusWatch *watch = reinterpret_cast<BusWatch *>(ew.data());
207
208 debug_log("watch %p ready, flags=%d state=%d",
209 watch, ((Watch *)watch)->flags(), watch->state()
210 );
211
212 int flags = 0;
213
214 if (watch->state() & POLLIN)
215 flags |= DBUS_WATCH_READABLE;
216 if (watch->state() & POLLOUT)
217 flags |= DBUS_WATCH_WRITABLE;
218 if (watch->state() & POLLHUP)
219 flags |= DBUS_WATCH_HANGUP;
220 if (watch->state() & POLLERR)
221 flags |= DBUS_WATCH_ERROR;
222
223 watch->handle(flags);
224}
225
std::list< Pipe * > pipe_list
virtual Pipe * add_pipe(void(*handler)(const void *data, void *buffer, unsigned int nbyte), const void *data)
virtual void del_pipe(Pipe *pipe)
void watch_ready(DefaultWatch &)
virtual Timeout * add_timeout(Timeout::Internal *)
virtual void rem_watch(Watch *)
void timeout_expired(DefaultTimeout &)
virtual void rem_timeout(Timeout *)
virtual Watch * add_watch(Watch::Internal *)
BusTimeout(Timeout::Internal *, BusDispatcher *)
BusWatch(Watch::Internal *, BusDispatcher *)
virtual void dispatch()
Slot< void, DefaultTimeout & > expired
Definition eventloop.h:90
Slot< void, DefaultWatch & > ready
Definition eventloop.h:155
ssize_t read(void *buffer, unsigned int &nbytes)
Definition pipe.cpp:73
void(* _handler)(const void *data, void *buffer, unsigned int nbyte)
Definition pipe.h:56
const void * _data
Definition pipe.h:59
bool enabled() const
bool handle()
Calls the timeout handler for this timeout.
bool enabled() const
int flags() const
Gets flags from DBusWatchFlags indicating what conditions should be monitored on the file descriptor.
bool handle(int flags)
Called to notify the D-Bus library when a previously-added watch is ready for reading or writing,...
std::string toString(const T &thing, int w=0, int p=0)
create std::string from any number
Definition util.h:294
DXXAPI LogFunction debug_log
Definition debug.cpp:55