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 
69  DefaultWatch::flags(flags);
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 {
149  dispatch();
150 }
151 
152 Timeout *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 
175 Watch *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 
Slot< void, DefaultWatch & > ready
Definition: eventloop.h:155
virtual void del_pipe(Pipe *pipe)
const void * _data
Definition: pipe.h:59
std::string toString(const T &thing, int w=0, int p=0)
create std::string from any number
Definition: util.h:297
bool enabled() const
Definition: dispatcher.cpp:91
virtual void rem_timeout(Timeout *)
DXXAPI LogFunction debug_log
Definition: debug.cpp:55
void dispatch_pending()
Definition: dispatcher.cpp:182
BusTimeout(Timeout::Internal *, BusDispatcher *)
Slot< void, DefaultTimeout & > expired
Definition: eventloop.h:90
void watch_ready(DefaultWatch &)
bool enabled() const
Definition: dispatcher.cpp:51
BusWatch(Watch::Internal *, BusDispatcher *)
void timeout_expired(DefaultTimeout &)
virtual Timeout * add_timeout(Timeout::Internal *)
virtual void dispatch()
Definition: eventloop.cpp:148
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
ssize_t read(void *buffer, unsigned int &nbytes)
Definition: pipe.cpp:73
std::list< Pipe * > pipe_list
virtual Watch * add_watch(Watch::Internal *)
virtual Pipe * add_pipe(void(*handler)(const void *data, void *buffer, unsigned int nbyte), const void *data)
int flags() const
Gets flags from DBusWatchFlags indicating what conditions should be monitored on the file descriptor...
Definition: dispatcher.cpp:86
bool handle()
Calls the timeout handler for this timeout.
Definition: dispatcher.cpp:56
virtual void rem_watch(Watch *)
void(* _handler)(const void *data, void *buffer, unsigned int nbyte)
Definition: pipe.h:56