diff options
-rw-r--r-- | .gitignore | 22 | ||||
-rw-r--r-- | Makefile.am | 2 | ||||
-rwxr-xr-x | bootstrap | 2 | ||||
-rw-r--r-- | configure.ac | 3 | ||||
-rw-r--r-- | examples/Makefile.am | 2 | ||||
-rw-r--r-- | examples/echo/echo-client.cpp | 79 | ||||
-rw-r--r-- | include/dbus-c++/dbus.h | 1 | ||||
-rw-r--r-- | include/dbus-c++/dispatcher.h | 2 | ||||
-rw-r--r-- | include/dbus-c++/ecore-integration.h | 6 | ||||
-rw-r--r-- | include/dbus-c++/eventloop-integration.h | 27 | ||||
-rw-r--r-- | include/dbus-c++/glib-integration.h | 4 | ||||
-rw-r--r-- | include/dbus-c++/pipe.h | 69 | ||||
-rw-r--r-- | include/dbus-c++/property.h | 2 | ||||
-rw-r--r-- | include/dbus-c++/util.h | 22 | ||||
-rw-r--r-- | m4/acx_pthread.m4 (renamed from config/acx_pthread.m4) | 0 | ||||
-rw-r--r-- | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/ecore-integration.cpp | 6 | ||||
-rw-r--r-- | src/eventloop-integration.cpp | 56 | ||||
-rw-r--r-- | src/eventloop.cpp | 4 | ||||
-rw-r--r-- | src/pipe.cpp | 84 |
20 files changed, 339 insertions, 57 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3cfba9c --- /dev/null +++ b/.gitignore @@ -0,0 +1,22 @@ +Makefile.in +aclocal.m4 +autom4te.cache/ +config.guess +config.h.in +config.sub +configure +data/Makefile.in +depcomp +doc/Makefile.in +examples/Makefile.in +examples/echo/Makefile.in +examples/ecore/Makefile.in +examples/glib/Makefile.in +examples/hal/Makefile.in +examples/properties/Makefile.in +install-sh +ltmain.sh +m4/ +missing +src/Makefile.in +tools/Makefile.in diff --git a/Makefile.am b/Makefile.am index 5df2cc8..912f64b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,6 +2,8 @@ SUBDIRS = src tools data doc examples EXTRA_DIST = autogen.sh bootstrap libdbus-c++.spec libdbus-c++.spec.in +ACLOCAL_AMFLAGS = -I m4 + pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = dbus-c++-1.pc @@ -58,7 +58,7 @@ fi echo "Running libtoolize..." libtoolize --force --copy -aclocalinclude="$ACLOCAL_FLAGS -I config" +aclocalinclude="$ACLOCAL_FLAGS -I m4" echo "Running aclocal $aclocalinclude ..." aclocal $aclocalinclude diff --git a/configure.ac b/configure.ac index 42f7199..1cdbb6f 100644 --- a/configure.ac +++ b/configure.ac @@ -1,10 +1,11 @@ # Autojunk script for libdbus-c++ AC_PREREQ(2.59) -AC_INIT([libdbus-c++], 0.5.0, [shackan@gmail.com]) +AC_INIT([libdbus-c++], 0.6.0-pre1, [andreas.volz@tux-style.com]) AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION) AM_CONFIG_HEADER([config.h]) +AC_CONFIG_MACRO_DIR([m4]) AC_CANONICAL_HOST diff --git a/examples/Makefile.am b/examples/Makefile.am index a940bc8..40fa245 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = properties echo hal glib ecore +DIST_SUBDIRS = properties echo hal glib ecore MAINTAINERCLEANFILES = \ Makefile.in diff --git a/examples/echo/echo-client.cpp b/examples/echo/echo-client.cpp index 8fe7ad7..f84c093 100644 --- a/examples/echo/echo-client.cpp +++ b/examples/echo/echo-client.cpp @@ -7,6 +7,7 @@ #include <pthread.h> #include <signal.h> #include <stdio.h> +#include <cstring> using namespace std; @@ -27,32 +28,31 @@ void EchoClient::Echoed(const DBus::Variant &value) * For some strange reason, libdbus frequently dies with an OOM */ -static const int THREADS = 3; +static const size_t THREADS = 3; static bool spin = true; -void *greeter_thread(void *arg) -{ - DBus::Connection *conn = reinterpret_cast<DBus::Connection *>(arg); +EchoClient *g_client = NULL; - EchoClient client(*conn, ECHO_SERVER_PATH, ECHO_SERVER_NAME); +DBus::Pipe *thread_pipe_list[THREADS]; +DBus::BusDispatcher dispatcher; +DBus::DefaultTimeout *timeout; + +void *greeter_thread(void *arg) +{ char idstr[16]; + size_t i = (size_t) arg; snprintf(idstr, sizeof(idstr), "%lu", pthread_self()); - for (int i = 0; i < 30 && spin; ++i) - { - cout << client.Hello(idstr) << endl; - } + thread_pipe_list[i]->write (idstr, strlen (idstr) + 1); - cout << idstr << " done " << endl; + cout << idstr << " done (" << i << ")" << endl; return NULL; } -DBus::BusDispatcher dispatcher; - void niam(int sig) { spin = false; @@ -60,32 +60,77 @@ void niam(int sig) dispatcher.leave(); } +void handler1 (const void *data, void *buffer, unsigned int nbyte) +{ + char *str = (char*) buffer; + cout << "buffer1: " << str << ", size: " << nbyte << endl; + for (int i = 0; i < 30 && spin; ++i) + { + cout << "call1: " << g_client->Hello (str) << endl; + } +} + +void handler2 (const void *data, void *buffer, unsigned int nbyte) +{ + char *str = (char*) buffer; + cout << "buffer2: " << str << ", size: " << nbyte <<endl; + for (int i = 0; i < 30 && spin; ++i) + { + cout << "call2: " << g_client->Hello (str) << endl; + } +} + +void handler3 (const void *data, void *buffer, unsigned int nbyte) +{ + char *str = (char*) buffer; + cout << "buffer3: " << str << ", size: " << nbyte <<endl; + for (int i = 0; i < 30 && spin; ++i) + { + cout << "call3: " << g_client->Hello (str) << endl; + } +} + int main() { + size_t i; + signal(SIGTERM, niam); signal(SIGINT, niam); DBus::_init_threading(); - DBus::default_dispatcher = &dispatcher; + DBus::default_dispatcher = &dispatcher; + + // increase DBus-C++ frequency + new DBus::DefaultTimeout(100, false, &dispatcher); DBus::Connection conn = DBus::Connection::SessionBus(); + EchoClient client (conn, ECHO_SERVER_PATH, ECHO_SERVER_NAME); + g_client = &client; + pthread_t threads[THREADS]; - for (int i = 0; i < THREADS; ++i) + thread_pipe_list[0] = dispatcher.add_pipe (handler1, NULL); + thread_pipe_list[1] = dispatcher.add_pipe (handler2, NULL); + thread_pipe_list[2] = dispatcher.add_pipe (handler3, NULL); + for (i = 0; i < THREADS; ++i) { - pthread_create(threads+i, NULL, greeter_thread, &conn); + pthread_create(threads+i, NULL, greeter_thread, (void*) i); } - + dispatcher.enter(); cout << "terminating" << endl; - for (int i = 0; i < THREADS; ++i) + for (i = 0; i < THREADS; ++i) { pthread_join(threads[i], NULL); } + dispatcher.del_pipe (thread_pipe_list[0]); + dispatcher.del_pipe (thread_pipe_list[1]); + dispatcher.del_pipe (thread_pipe_list[2]); + return 0; } diff --git a/include/dbus-c++/dbus.h b/include/dbus-c++/dbus.h index 7dfc164..80893cb 100644 --- a/include/dbus-c++/dbus.h +++ b/include/dbus-c++/dbus.h @@ -41,5 +41,6 @@ #include "eventloop.h" #include "eventloop-integration.h" #include "introspection.h" +#include "pipe.h" #endif//__DBUSXX_DBUS_H diff --git a/include/dbus-c++/dispatcher.h b/include/dbus-c++/dispatcher.h index 10179ff..728f9d8 100644 --- a/include/dbus-c++/dispatcher.h +++ b/include/dbus-c++/dispatcher.h @@ -44,7 +44,7 @@ public: /*! * \brief Gets the timeout interval. * - * The dbus_timeout_handle() should be called each time this interval elapses, + * The handle() should be called each time this interval elapses, * starting after it elapses once. * * The interval may change during the life of the timeout; if so, the timeout diff --git a/include/dbus-c++/ecore-integration.h b/include/dbus-c++/ecore-integration.h index b475533..2b14b27 100644 --- a/include/dbus-c++/ecore-integration.h +++ b/include/dbus-c++/ecore-integration.h @@ -47,7 +47,7 @@ private: void toggle(); - static int timeout_handler( void* ); + static Eina_Bool timeout_handler( void* ); void _enable(); @@ -69,9 +69,9 @@ private: void toggle(); - static int watch_handler_read ( void*, Ecore_Fd_Handler *fdh); + static Eina_Bool watch_handler_read ( void*, Ecore_Fd_Handler *fdh); - static int watch_handler_error ( void*, Ecore_Fd_Handler *fdh); + static Eina_Bool watch_handler_error ( void*, Ecore_Fd_Handler *fdh); void _enable(); diff --git a/include/dbus-c++/eventloop-integration.h b/include/dbus-c++/eventloop-integration.h index b8e02c7..0459ebf 100644 --- a/include/dbus-c++/eventloop-integration.h +++ b/include/dbus-c++/eventloop-integration.h @@ -38,6 +38,7 @@ namespace DBus { */ class BusDispatcher; +class Pipe; class DXXAPI BusTimeout : public Timeout, public DefaultTimeout { @@ -60,27 +61,18 @@ friend class BusDispatcher; class DXXAPI BusDispatcher : public Dispatcher, public DefaultMainLoop { public: - - int _pipe[2]; - - BusDispatcher() : _running(false) - { - //pipe to create a new fd used to unlock a dispatcher at any - // moment (used by leave function) - int ret = pipe(_pipe); - if (ret == -1) throw Error("PipeError:errno", toString(errno).c_str()); - - _fdunlock[0] = _pipe[0]; - _fdunlock[1] = _pipe[1]; - } - - ~BusDispatcher() - {} + BusDispatcher(); + + ~BusDispatcher() {} virtual void enter(); virtual void leave(); + virtual Pipe *add_pipe(void(*handler)(const void *data, void *buffer, unsigned int nbyte), const void *data); + + virtual void del_pipe (Pipe *pipe); + virtual void do_iteration(); virtual Timeout *add_timeout(Timeout::Internal *); @@ -96,8 +88,9 @@ public: void timeout_expired(DefaultTimeout &); private: - bool _running; + int _pipe[2]; + std::list <Pipe*> pipe_list; }; } /* namespace DBus */ diff --git a/include/dbus-c++/glib-integration.h b/include/dbus-c++/glib-integration.h index 76eae5e..0f68852 100644 --- a/include/dbus-c++/glib-integration.h +++ b/include/dbus-c++/glib-integration.h @@ -54,9 +54,9 @@ private: private: - GSource *_source; GMainContext *_ctx; int _priority; + GSource *_source; friend class BusDispatcher; }; @@ -79,9 +79,9 @@ private: private: - GSource *_source; GMainContext *_ctx; int _priority; + GSource *_source; friend class BusDispatcher; }; diff --git a/include/dbus-c++/pipe.h b/include/dbus-c++/pipe.h new file mode 100644 index 0000000..752d48d --- /dev/null +++ b/include/dbus-c++/pipe.h @@ -0,0 +1,69 @@ +/* + * + * D-Bus++ - C++ bindings for D-Bus + * + * Copyright (C) 2005-2007 Paolo Durante <shackan@gmail.com> + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef DBUSXX_PIPE_H +#define DBUSXX_PIPE_H + +/* Project */ +#include "api.h" + +/* STD */ +#include <cstdlib> + +namespace DBus { + +class DXXAPI Pipe +{ +public: + /*! + * Write some data into the communication pipe. + * + * @param buffer The raw data to write. + * @param nbytes The number of bytes to write from the buffer. + */ + void write(const void *buffer, unsigned int nbytes); + + ssize_t read(void *buffer, unsigned int &nbytes); + + /*! + * Simply write one single byte into the pipe. This is a shortcut + * if there's really no data to transport, but to activate the handler. + */ + void signal(); + +private: + void(*_handler)(const void *data, void *buffer, unsigned int nbyte); + int _fd_write; + int _fd_read; + const void *_data; + + // allow construction only in BusDispatcher + Pipe (void(*handler)(const void *data, void *buffer, unsigned int nbyte), const void *data); + ~Pipe () {}; + +friend class BusDispatcher; +}; + +} /* namespace DBus */ + +#endif // DBUSXX_PIPE_H diff --git a/include/dbus-c++/property.h b/include/dbus-c++/property.h index 2e909cb..847ae89 100644 --- a/include/dbus-c++/property.h +++ b/include/dbus-c++/property.h @@ -46,7 +46,7 @@ public: T operator() (void) const { - return (T)_data->value; + return _data->value.operator T(); } PropertyAdaptor &operator = (const T &t) diff --git a/include/dbus-c++/util.h b/include/dbus-c++/util.h index b46732f..8b3806d 100644 --- a/include/dbus-c++/util.h +++ b/include/dbus-c++/util.h @@ -28,6 +28,8 @@ #include <sstream> #include <iostream> #include <iomanip> +#include <cassert> + #include "api.h" #include "debug.h" @@ -232,15 +234,29 @@ public: R operator()(P param) const { - /*if (_cb.get())*/ return _cb->call(param); + if (!empty()) + { + return _cb->call(param); + } + + // TODO: think about return type in this case + // this assert should help me to find the use case where it's needed... + //assert (false); } R call(P param) const { - /*if (_cb.get())*/ return _cb->call(param); + if (!empty()) + { + return _cb->call(param); + } + + // TODO: think about return type in this case + // this assert should help me to find the use case where it's needed... + //assert (false); } - bool empty() + bool empty() const { return _cb.get() == 0; } diff --git a/config/acx_pthread.m4 b/m4/acx_pthread.m4 index eb09f5a..eb09f5a 100644 --- a/config/acx_pthread.m4 +++ b/m4/acx_pthread.m4 diff --git a/src/Makefile.am b/src/Makefile.am index 1220db5..538c031 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -36,13 +36,14 @@ HEADER_FILES = \ $(HEADER_DIR)/api.h \ $(HEADER_DIR)/eventloop.h \ $(HEADER_DIR)/eventloop-integration.h \ + $(HEADER_DIR)/pipe.h \ $(GLIB_H) $(ECORE_H) lib_includedir=$(includedir)/dbus-c++-1/dbus-c++/ lib_include_HEADERS = $(HEADER_FILES) lib_LTLIBRARIES = libdbus-c++-1.la -libdbus_c___1_la_SOURCES = $(HEADER_FILES) interface.cpp object.cpp introspection.cpp debug.cpp types.cpp connection.cpp connection_p.h property.cpp dispatcher.cpp dispatcher_p.h pendingcall.cpp pendingcall_p.h error.cpp internalerror.h message.cpp message_p.h server.cpp server_p.h eventloop.cpp eventloop-integration.cpp $(GLIB_CPP) $(ECORE_CPP) +libdbus_c___1_la_SOURCES = $(HEADER_FILES) interface.cpp object.cpp introspection.cpp debug.cpp types.cpp connection.cpp connection_p.h property.cpp dispatcher.cpp dispatcher_p.h pendingcall.cpp pendingcall_p.h error.cpp internalerror.h message.cpp message_p.h server.cpp server_p.h eventloop.cpp eventloop-integration.cpp pipe.cpp $(GLIB_CPP) $(ECORE_CPP) libdbus_c___1_la_LIBADD = $(dbus_LIBS) $(glib_LIBS) $(pthread_LIBS) $(ecore_LIBS) libdbus_c___1_la_LDFLAGS = -no-undefined diff --git a/src/ecore-integration.cpp b/src/ecore-integration.cpp index e530e06..f1e24e7 100644 --- a/src/ecore-integration.cpp +++ b/src/ecore-integration.cpp @@ -50,7 +50,7 @@ void Ecore::BusTimeout::toggle() else _disable(); } -int Ecore::BusTimeout::timeout_handler( void *data ) +Eina_Bool Ecore::BusTimeout::timeout_handler( void *data ) { Ecore::BusTimeout* t = reinterpret_cast<Ecore::BusTimeout*>(data); @@ -118,7 +118,7 @@ void Ecore::BusWatch::toggle() else _disable(); } -int Ecore::BusWatch::watch_handler_read( void *data, Ecore_Fd_Handler *fdh ) +Eina_Bool Ecore::BusWatch::watch_handler_read( void *data, Ecore_Fd_Handler *fdh ) { Ecore::BusWatch* w = reinterpret_cast<Ecore::BusWatch*>(data); @@ -133,7 +133,7 @@ int Ecore::BusWatch::watch_handler_read( void *data, Ecore_Fd_Handler *fdh ) return 1; } -int Ecore::BusWatch::watch_handler_error( void *data, Ecore_Fd_Handler *fdh ) +Eina_Bool Ecore::BusWatch::watch_handler_error( void *data, Ecore_Fd_Handler *fdh ) { //Ecore::BusWatch* w = reinterpret_cast<Ecore::BusWatch*>(data); diff --git a/src/eventloop-integration.cpp b/src/eventloop-integration.cpp index 8b9c49b..0c86ffb 100644 --- a/src/eventloop-integration.cpp +++ b/src/eventloop-integration.cpp @@ -25,17 +25,22 @@ #include <config.h> #endif -#include <string.h> - +/* Project */ #include <dbus-c++/eventloop-integration.h> #include <dbus-c++/debug.h> +#include <dbus-c++/pipe.h> -#include <sys/poll.h> - +/* DBus */ #include <dbus/dbus.h> -#include <errno.h> + +/* STD */ +#include <string.h> +#include <cassert> +#include <sys/poll.h> +#include <fcntl.h> using namespace DBus; +using namespace std; BusTimeout::BusTimeout(Timeout::Internal *ti, BusDispatcher *bd) : Timeout(ti), DefaultTimeout(Timeout::interval(), true, bd) @@ -71,6 +76,18 @@ void BusWatch::toggle() DefaultWatch::enabled(Watch::enabled()); } +BusDispatcher::BusDispatcher() : + _running(false) +{ + // pipe to create a new fd used to unlock a dispatcher at any + // moment (used by leave function) + int ret = pipe(_pipe); + if (ret == -1) throw Error("PipeError:errno", toString(errno).c_str()); + + _fdunlock[0] = _pipe[0]; + _fdunlock[1] = _pipe[1]; +} + void BusDispatcher::enter() { debug_log("entering dispatcher %p", this); @@ -80,6 +97,21 @@ void BusDispatcher::enter() while (_running) { do_iteration(); + + for (std::list <Pipe*>::iterator p_it = pipe_list.begin (); + p_it != pipe_list.end (); + ++p_it) + { + Pipe* read_pipe = *p_it; + char buffer[1024]; // TODO: should be max pipe size + unsigned int nbytes = 0; + + while (read_pipe->read(buffer, nbytes) > 0) + { + read_pipe->_handler (read_pipe->_data, buffer, nbytes); + } + + } } debug_log("leaving dispatcher %p", this); @@ -96,6 +128,20 @@ void BusDispatcher::leave() close(_fdunlock[0]); } +Pipe *BusDispatcher::add_pipe(void(*handler)(const void *data, void *buffer, unsigned int nbyte), const void *data) +{ + Pipe *new_pipe = new Pipe (handler, data); + pipe_list.push_back (new_pipe); + + return new_pipe; +} + +void BusDispatcher::del_pipe (Pipe *pipe) +{ + pipe_list.remove (pipe); + delete pipe; +} + void BusDispatcher::do_iteration() { dispatch_pending(); diff --git a/src/eventloop.cpp b/src/eventloop.cpp index 76b94f8..eb2ce85 100644 --- a/src/eventloop.cpp +++ b/src/eventloop.cpp @@ -34,6 +34,7 @@ #include <dbus/dbus.h> using namespace DBus; +using namespace std; static double millis(timeval tv) { @@ -108,7 +109,8 @@ void DefaultMutex::unlock() pthread_mutex_unlock(&_mutex); } -DefaultMainLoop::DefaultMainLoop() +DefaultMainLoop::DefaultMainLoop() : + _mutex_w(true) { } diff --git a/src/pipe.cpp b/src/pipe.cpp new file mode 100644 index 0000000..96f1b30 --- /dev/null +++ b/src/pipe.cpp @@ -0,0 +1,84 @@ +/* + * + * D-Bus++ - C++ bindings for D-Bus + * + * Copyright (C) 2005-2007 Paolo Durante <shackan@gmail.com> + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +/* Project */ +#include <dbus-c++/pipe.h> +#include <dbus-c++/util.h> +#include <dbus-c++/error.h> + +/* STD */ +#include <unistd.h> +#include <sys/poll.h> +#include <fcntl.h> +#include <errno.h> +#include <cassert> + +using namespace DBus; +using namespace std; + +Pipe::Pipe(void(*handler)(const void *data, void *buffer, unsigned int nbyte), const void *data) : + _handler(handler), + _fd_write (0), + _fd_read (0), + _data(data) +{ + int fd[2]; + + if(pipe(fd) == 0) + { + _fd_read = fd[0]; + _fd_write = fd[1]; + fcntl(_fd_read, F_SETFL, O_NONBLOCK); + } + else + { + throw Error("PipeError:errno", toString(errno).c_str()); + } +} + +void Pipe::write(const void *buffer, unsigned int nbytes) +{ + // first write the size into the pipe... + ::write(_fd_write, static_cast <const void*> (&nbytes), sizeof(nbytes)); + + // ...then write the real data + ::write(_fd_write, buffer, nbytes); +} + +ssize_t Pipe::read(void *buffer, unsigned int &nbytes) +{ + // first read the size from the pipe... + ::read(_fd_read, &nbytes, sizeof (nbytes)); + + //ssize_t size = 0; + return ::read(_fd_read, buffer, nbytes); +} + +void Pipe::signal() +{ + ::write(_fd_write, '\0', 1); +} |