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 #include <unistd.h>
42 
43 using namespace DBus;
44 using namespace std;
45 
46 BusTimeout::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 
59 BusWatch::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 
132 Pipe *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 
147 {
148  _running = true;
149 }
150 
152 {
153  return _running;
154 }
155 
157 {
159  dispatch();
160 }
161 
162 Timeout *BusDispatcher::add_timeout(Timeout::Internal *ti)
163 {
164  BusTimeout *bt = new BusTimeout(ti, this);
165 
167  bt->data(bt);
168 
169  debug_log("added timeout %p (%s) (%d millies)",
170  bt,
171  ((Timeout *)bt)->enabled() ? "on" : "off",
172  ((Timeout *)bt)->interval()
173  );
174 
175  return bt;
176 }
177 
179 {
180  debug_log("removed timeout %p", t);
181 
182  delete t;
183 }
184 
185 Watch *BusDispatcher::add_watch(Watch::Internal *wi)
186 {
187  BusWatch *bw = new BusWatch(wi, this);
188 
190  bw->data(bw);
191 
192  debug_log("added watch %p (%s) fd=%d flags=%d",
193  bw, ((Watch *)bw)->enabled() ? "on" : "off", ((Watch *)bw)->descriptor(), ((Watch *)bw)->flags());
194 
195  return bw;
196 }
197 
199 {
200  debug_log("removed watch %p", w);
201 
202  delete w;
203 }
204 
206 {
207  debug_log("timeout %p expired", &et);
208 
209  BusTimeout *timeout = reinterpret_cast<BusTimeout *>(et.data());
210 
211  timeout->handle();
212 }
213 
215 {
216  BusWatch *watch = reinterpret_cast<BusWatch *>(ew.data());
217 
218  debug_log("watch %p ready, flags=%d state=%d",
219  watch, ((Watch *)watch)->flags(), watch->state()
220  );
221 
222  int flags = 0;
223 
224  if (watch->state() & POLLIN)
225  flags |= DBUS_WATCH_READABLE;
226  if (watch->state() & POLLOUT)
227  flags |= DBUS_WATCH_WRITABLE;
228  if (watch->state() & POLLHUP)
229  flags |= DBUS_WATCH_HANGUP;
230  if (watch->state() & POLLERR)
231  flags |= DBUS_WATCH_ERROR;
232 
233  watch->handle(flags);
234 }
235 
bool enabled() const
Definition: dispatcher.cpp:51
BusWatch(Watch::Internal *, BusDispatcher *)
void(* _handler)(const void *data, void *buffer, unsigned int nbyte)
Definition: pipe.h:56
void dispatch_pending()
Definition: dispatcher.cpp:182
bool enabled() const
Definition: dispatcher.cpp:91
BusTimeout(Timeout::Internal *, BusDispatcher *)
Slot< void, DefaultWatch & > ready
Definition: eventloop.h:155
Slot< void, DefaultTimeout & > expired
Definition: eventloop.h:90
virtual void rem_watch(Watch *)
virtual Watch * add_watch(Watch::Internal *)
bool handle(int flags)
Called to notify the D-Bus library when a previously-added watch is ready for reading or writing,...
Definition: dispatcher.cpp:96
int flags() const
Gets flags from DBusWatchFlags indicating what conditions should be monitored on the file descriptor.
Definition: dispatcher.cpp:86
void timeout_expired(DefaultTimeout &)
const void * _data
Definition: pipe.h:59
virtual void rem_timeout(Timeout *)
ssize_t read(void *buffer, unsigned int &nbytes)
Definition: pipe.cpp:73
virtual Pipe * add_pipe(void(*handler)(const void *data, void *buffer, unsigned int nbyte), const void *data)
DXXAPI LogFunction debug_log
Definition: debug.cpp:55
std::list< Pipe * > pipe_list
bool handle()
Calls the timeout handler for this timeout.
Definition: dispatcher.cpp:56
virtual Timeout * add_timeout(Timeout::Internal *)
std::string toString(const T &thing, int w=0, int p=0)
create std::string from any number
Definition: util.h:297
void watch_ready(DefaultWatch &)
virtual void dispatch()
Definition: eventloop.cpp:148
virtual void del_pipe(Pipe *pipe)