Merge branch 'master' of git@gitorious.org:dbus-cplusplus/mainline

This commit is contained in:
Andreas Volz 2010-12-05 23:09:30 +01:00
commit 2a42e69250
20 changed files with 339 additions and 57 deletions

22
.gitignore vendored Normal file
View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -1,4 +1,4 @@
SUBDIRS = properties echo hal glib ecore
DIST_SUBDIRS = properties echo hal glib ecore
MAINTAINERCLEANFILES = \
Makefile.in

View file

@ -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;
EchoClient *g_client = NULL;
DBus::Pipe *thread_pipe_list[THREADS];
DBus::BusDispatcher dispatcher;
DBus::DefaultTimeout *timeout;
void *greeter_thread(void *arg)
{
DBus::Connection *conn = reinterpret_cast<DBus::Connection *>(arg);
EchoClient client(*conn, ECHO_SERVER_PATH, ECHO_SERVER_NAME);
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;
}

View file

@ -41,5 +41,6 @@
#include "eventloop.h"
#include "eventloop-integration.h"
#include "introspection.h"
#include "pipe.h"
#endif//__DBUSXX_DBUS_H

View file

@ -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

View file

@ -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();

View file

@ -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 */

View file

@ -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;
};

69
include/dbus-c++/pipe.h Normal file
View file

@ -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

View file

@ -46,7 +46,7 @@ public:
T operator() (void) const
{
return (T)_data->value;
return _data->value.operator T();
}
PropertyAdaptor &operator = (const T &t)

View file

@ -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;
}

View file

@ -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

View file

@ -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);

View file

@ -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();

View file

@ -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)
{
}

84
src/pipe.cpp Normal file
View file

@ -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);
}