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 <string.h>
38 #include <cassert>
39 #include <sys/poll.h>
40 #include <fcntl.h>
41 
42 using namespace DBus;
43 using namespace std;
44 
45 BusTimeout::BusTimeout(Timeout::Internal *ti, BusDispatcher *bd)
46  : Timeout(ti), DefaultTimeout(Timeout::interval(), true, bd)
47 {
49 }
50 
52 {
53  debug_log("timeout %p toggled (%s)", this, Timeout::enabled() ? "on" : "off");
54 
56 }
57 
58 BusWatch::BusWatch(Watch::Internal *wi, BusDispatcher *bd)
59  : Watch(wi), DefaultWatch(Watch::descriptor(), 0, bd)
60 {
61  int flags = POLLHUP | POLLERR;
62 
63  if (Watch::flags() & DBUS_WATCH_READABLE)
64  flags |= POLLIN;
65  if (Watch::flags() & DBUS_WATCH_WRITABLE)
66  flags |= POLLOUT;
67 
68  DefaultWatch::flags(flags);
70 }
71 
73 {
74  debug_log("watch %p toggled (%s)", this, Watch::enabled() ? "on" : "off");
75 
77 }
78 
80  _running(false)
81 {
82  // pipe to create a new fd used to unlock a dispatcher at any
83  // moment (used by leave function)
84  int ret = pipe(_pipe);
85  if (ret == -1) throw Error("PipeError:errno", toString(errno).c_str());
86 
87  _fdunlock[0] = _pipe[0];
88  _fdunlock[1] = _pipe[1];
89 }
90 
92 {
93  debug_log("entering dispatcher %p", this);
94 
95  _running = true;
96 
97  while (_running)
98  {
99  do_iteration();
100 
101  for (std::list <Pipe *>::iterator p_it = pipe_list.begin();
102  p_it != pipe_list.end();
103  ++p_it)
104  {
105  Pipe *read_pipe = *p_it;
106  char buffer[1024]; // TODO: should be max pipe size
107  unsigned int nbytes = 0;
108 
109  while (read_pipe->read(buffer, nbytes) > 0)
110  {
111  read_pipe->_handler(read_pipe->_data, buffer, nbytes);
112  }
113 
114  }
115  }
116 
117  debug_log("leaving dispatcher %p", this);
118 }
119 
121 {
122  _running = false;
123 
124  int ret = write(_fdunlock[1], "exit", strlen("exit"));
125  if (ret == -1) throw Error("WriteError:errno", toString(errno).c_str());
126 
127  close(_fdunlock[1]);
128  close(_fdunlock[0]);
129 }
130 
131 Pipe *BusDispatcher::add_pipe(void(*handler)(const void *data, void *buffer, unsigned int nbyte), const void *data)
132 {
133  Pipe *new_pipe = new Pipe(handler, data);
134  pipe_list.push_back(new_pipe);
135 
136  return new_pipe;
137 }
138 
140 {
141  pipe_list.remove(pipe);
142  delete pipe;
143 }
144 
146 {
148  dispatch();
149 }
150 
151 Timeout *BusDispatcher::add_timeout(Timeout::Internal *ti)
152 {
153  BusTimeout *bt = new BusTimeout(ti, this);
154 
156  bt->data(bt);
157 
158  debug_log("added timeout %p (%s) (%d millies)",
159  bt,
160  ((Timeout *)bt)->enabled() ? "on" : "off",
161  ((Timeout *)bt)->interval()
162  );
163 
164  return bt;
165 }
166 
168 {
169  debug_log("removed timeout %p", t);
170 
171  delete t;
172 }
173 
174 Watch *BusDispatcher::add_watch(Watch::Internal *wi)
175 {
176  BusWatch *bw = new BusWatch(wi, this);
177 
179  bw->data(bw);
180 
181  debug_log("added watch %p (%s) fd=%d flags=%d",
182  bw, ((Watch *)bw)->enabled() ? "on" : "off", ((Watch *)bw)->descriptor(), ((Watch *)bw)->flags());
183 
184  return bw;
185 }
186 
188 {
189  debug_log("removed watch %p", w);
190 
191  delete w;
192 }
193 
195 {
196  debug_log("timeout %p expired", &et);
197 
198  BusTimeout *timeout = reinterpret_cast<BusTimeout *>(et.data());
199 
200  timeout->handle();
201 }
202 
204 {
205  BusWatch *watch = reinterpret_cast<BusWatch *>(ew.data());
206 
207  debug_log("watch %p ready, flags=%d state=%d",
208  watch, ((Watch *)watch)->flags(), watch->state()
209  );
210 
211  int flags = 0;
212 
213  if (watch->state() & POLLIN)
214  flags |= DBUS_WATCH_READABLE;
215  if (watch->state() & POLLOUT)
216  flags |= DBUS_WATCH_WRITABLE;
217  if (watch->state() & POLLHUP)
218  flags |= DBUS_WATCH_HANGUP;
219  if (watch->state() & POLLERR)
220  flags |= DBUS_WATCH_ERROR;
221 
222  watch->handle(flags);
223 }
224