summaryrefslogtreecommitdiff
path: root/src/gdbusxx
diff options
context:
space:
mode:
authorPatrick Ohly <patrick.ohly@intel.com>2012-09-11 15:28:07 +0200
committerPatrick Ohly <patrick.ohly@intel.com>2012-10-25 16:43:45 +0200
commitcec68658987d99da8db3fdde4ad61b2fb44a310b (patch)
tree33c41f5a9f3de46f39fac9ee04b784a7d981bbfe /src/gdbusxx
parent3004545b0ccee6657cce3f38d0bc5bae2a8d66b6 (diff)
GDBus GIO: revamped name owning
Remove global variables and allow addditional names to be owned via DBusConnectionPtr::ownName(). g_bus_own_name_on_connection() is given shared access to a ref-counted OwnNameAsyncData (instead of full ownership) because that way it is guaranteed that the instance is still around while waiting for name acquisition in undelay().
Diffstat (limited to 'src/gdbusxx')
-rw-r--r--src/gdbusxx/gdbus-cxx-bridge.cpp118
-rw-r--r--src/gdbusxx/gdbus-cxx-bridge.h24
2 files changed, 102 insertions, 40 deletions
diff --git a/src/gdbusxx/gdbus-cxx-bridge.cpp b/src/gdbusxx/gdbus-cxx-bridge.cpp
index ea6aaefe..8dee2c8d 100644
--- a/src/gdbusxx/gdbus-cxx-bridge.cpp
+++ b/src/gdbusxx/gdbus-cxx-bridge.cpp
@@ -33,65 +33,103 @@ namespace GDBusCXX {
MethodHandler::MethodMap MethodHandler::m_methodMap;
boost::function<void (void)> MethodHandler::m_callback;
-// It should be okay to use global variables here because they are
-// only used inside the main thread while it waits in undelay() for a
-// positive or negative result to g_bus_own_name_on_connection().
-// Once acquired, the name can only get lost again when the
-// D-Bus daemon dies (no name owership alloed), in which case the
-// process dies anyway.
-static bool nameError;
-static bool nameAcquired;
-static void BusNameAcquired(GDBusConnection *connection,
+struct OwnNameAsyncData
+{
+ enum State {
+ OWN_NAME_WAITING,
+ OWN_NAME_OBTAINED,
+ OWN_NAME_LOST
+ };
+
+ OwnNameAsyncData(const std::string &name,
+ const boost::function<void (bool)> &obtainedCB) :
+ m_name(name),
+ m_obtainedCB(obtainedCB),
+ m_state(OWN_NAME_WAITING)
+ {}
+
+ static void busNameAcquired(GDBusConnection *connection,
+ const gchar *name,
+ gpointer userData) throw ()
+ {
+ boost::shared_ptr<OwnNameAsyncData> *data = static_cast< boost::shared_ptr<OwnNameAsyncData> *>(userData);
+ (*data)->m_state = OWN_NAME_OBTAINED;
+ try {
+ g_debug("got D-Bus name %s", name);
+ if ((*data)->m_obtainedCB) {
+ (*data)->m_obtainedCB(true);
+ }
+ } catch (...) {
+ (*data)->m_state = OWN_NAME_LOST;
+ }
+ }
+
+ static void busNameLost(GDBusConnection *connection,
const gchar *name,
gpointer userData) throw ()
-{
- try {
- g_debug("got D-Bus name %s", name);
- nameAcquired = true;
- } catch (...) {
- nameError = true;
+ {
+ boost::shared_ptr<OwnNameAsyncData> *data = static_cast< boost::shared_ptr<OwnNameAsyncData> *>(userData);
+ (*data)->m_state = OWN_NAME_LOST;
+ try {
+ g_debug("lost %s %s",
+ connection ? "D-Bus connection for name" :
+ "D-Bus name",
+ name);
+ if ((*data)->m_obtainedCB) {
+ (*data)->m_obtainedCB(false);
+ }
+ } catch (...) {
+ }
}
-}
-static void BusNameLost(GDBusConnection *connection,
- const gchar *name,
- gpointer userData) throw ()
-{
- try {
- g_debug("lost %s %s",
- connection ? "D-Bus connection for name" :
- "D-Bus name",
- name);
- } catch (...) {
+ static void freeData(gpointer userData) throw ()
+ {
+ delete static_cast< boost::shared_ptr<OwnNameAsyncData> *>(userData);
+ }
+
+ static boost::shared_ptr<OwnNameAsyncData> ownName(GDBusConnection *conn,
+ const std::string &name,
+ boost::function<void (bool)> obtainedCB =
+ boost::function<void (bool)>()) {
+ boost::shared_ptr<OwnNameAsyncData> data(new OwnNameAsyncData(name, obtainedCB));
+ g_bus_own_name_on_connection(conn,
+ data->m_name.c_str(),
+ G_BUS_NAME_OWNER_FLAGS_NONE,
+ OwnNameAsyncData::busNameAcquired,
+ OwnNameAsyncData::busNameLost,
+ new boost::shared_ptr<OwnNameAsyncData>(data),
+ OwnNameAsyncData::freeData);
+ return data;
}
- nameError = true;
-}
+
+ const std::string m_name;
+ const boost::function<void (bool)> m_obtainedCB;
+ State m_state;
+};
void DBusConnectionPtr::undelay() const
{
if (!m_name.empty()) {
g_debug("starting to acquire D-Bus name %s", m_name.c_str());
- nameAcquired = false;
- nameError = false;
- char *copy = g_strdup(m_name.c_str());
- g_bus_own_name_on_connection(get(),
- copy,
- G_BUS_NAME_OWNER_FLAGS_NONE,
- BusNameAcquired,
- BusNameLost,
- copy,
- g_free);
- while (!nameAcquired && !nameError) {
+ boost::shared_ptr<OwnNameAsyncData> data = OwnNameAsyncData::ownName(get(),
+ m_name);
+ while (data->m_state == OwnNameAsyncData::OWN_NAME_WAITING) {
g_main_context_iteration(NULL, true);
}
g_debug("done with acquisition of %s", m_name.c_str());
- if (nameError) {
+ if (data->m_state == OwnNameAsyncData::OWN_NAME_LOST) {
throw std::runtime_error("could not obtain D-Bus name - already running?");
}
}
g_dbus_connection_start_message_processing(get());
}
+void DBusConnectionPtr::ownNameAsync(const std::string &name,
+ const boost::function<void (bool)> &obtainedCB) const
+{
+ OwnNameAsyncData::ownName(get(), name, obtainedCB);
+}
+
DBusConnectionPtr dbus_get_bus_connection(const char *busType,
const char *name,
bool unshared,
diff --git a/src/gdbusxx/gdbus-cxx-bridge.h b/src/gdbusxx/gdbus-cxx-bridge.h
index e5bccee2..07a4ad3f 100644
--- a/src/gdbusxx/gdbus-cxx-bridge.h
+++ b/src/gdbusxx/gdbus-cxx-bridge.h
@@ -186,8 +186,32 @@ class DBusConnectionPtr : public boost::intrusive_ptr<GDBusConnection>
void setDisconnect(const Disconnect_t &func);
// #define GDBUS_CXX_HAVE_DISCONNECT 1
+ /**
+ * Starts processing of messages,
+ * claims the bus name set with addName() or
+ * when creating the connection (legacy API,
+ * done that way for compatibility with GDBus for libdbus).
+ */
void undelay() const;
void addName(const std::string &name) { m_name = name; }
+
+ /**
+ * Claims another name on the connection.
+ *
+ * The callback will be invoked with true as
+ * parameter once the name was successfully
+ * claimed. If that fails, false will be passed.
+ *
+ * The caller should be prepared to get called
+ * again later on, when loosing an already obtained
+ * name. Currently this shouldn't happen, though,
+ * because name transfer is not enabled when
+ * registering the name.
+ *
+ * The callback is allowed to be empty.
+ */
+ void ownNameAsync(const std::string &name,
+ const boost::function<void (bool)> &obtainedCB) const;
};
class DBusMessagePtr : public boost::intrusive_ptr<GDBusMessage>