ServiceRunner::ServiceRunner(GDBusConnection* conn, IService* service) :
__service(service),
__started(false),
- __threadRunning(false),
- __mainContext(NULL),
- __mainLoop(NULL),
- __gthread(NULL),
__connection(conn),
__objPath(CTX_DBUS_PATH "/"),
__interface(CTX_DBUS_IFACE "."),
GMainContext* ServiceRunner::getMainContext()
{
- return __mainContext;
+ return g_main_context_default();
}
GDBusConnection* ServiceRunner::getConnection()
{
IF_FAIL_RETURN(!__started, true);
- _I("Preparing '%s'", __service->getServiceName());
+ _I(CYAN("Starting '%s'"), __service->getServiceName());
- __gthread = g_thread_new(__service->getServiceName(), __threadFunc, this);
- IF_FAIL_RETURN_TAG(__gthread, false, _E, "Thread creation failed");
+ if (!__init()) {
+ _E("Starting failed");
+ __release();
+ return false;
+ }
__started = true;
return true;
IF_FAIL_VOID(__started);
__started = false;
- IF_FAIL_VOID(__threadRunning.load());
-
- GSource *gSrc = g_idle_source_new();
- if (gSrc) {
- // Tries to stop the main loop within its thread.
- // In this way, already scheduled idle tasks are not discarded.
- g_source_set_callback(gSrc, __stopMainLoop, this, NULL);
- g_source_attach(gSrc, __mainContext);
- g_source_unref(gSrc);
- } else {
- __stopMainLoop(this);
- }
+ _I(PURPLE("Stopping '%s'"), __service->getServiceName());
- _I("Joining the thread of '%s'", __service->getServiceName());
- g_thread_join(__gthread);
- __gthread = NULL;
-}
-
-gboolean ServiceRunner::__stopMainLoop(gpointer data)
-{
- ServiceRunner* runner = static_cast<ServiceRunner*>(data);
- _I(PURPLE("Stopping '%s'"), runner->__service->getServiceName());
- g_main_loop_quit(runner->__mainLoop);
- return G_SOURCE_REMOVE;
+ __release();
}
void ServiceRunner::publish(const std::string& busName, const std::string& signalName, GVariant* param)
void ServiceRunner::notifyUserNew()
{
- IF_FAIL_VOID(__started);
- IF_FAIL_VOID(__threadRunning.load());
-
- GSource* gSrc = g_idle_source_new();
- IF_FAIL_VOID_TAG(gSrc, _E, E_STR_ALLOC);
-
- g_source_set_callback(gSrc, __onUserActivated, __service, NULL);
- g_source_attach(gSrc, __mainContext);
- g_source_unref(gSrc);
+ if (__started)
+ __service->onUserActivated();
}
void ServiceRunner::notifyUserRemoved()
{
- IF_FAIL_VOID(__started);
- IF_FAIL_VOID(__threadRunning.load());
-
- GSource* gSrc = g_idle_source_new();
- IF_FAIL_VOID_TAG(gSrc, _E, E_STR_ALLOC);
-
- g_source_set_callback(gSrc, __onUserDeactivated, __service, NULL);
- g_source_attach(gSrc, __mainContext);
- g_source_unref(gSrc);
-}
-
-gboolean ServiceRunner::__onUserActivated(gpointer data)
-{
- IService* svc = static_cast<IService*>(data);
- svc->onUserActivated();
- return G_SOURCE_REMOVE;
-}
-
-gboolean ServiceRunner::__onUserDeactivated(gpointer data)
-{
- IService* svc = static_cast<IService*>(data);
- svc->onUserDeactivated();
- return G_SOURCE_REMOVE;
-}
-
-gpointer ServiceRunner::__threadFunc(gpointer data)
-{
- ServiceRunner* runner = static_cast<ServiceRunner*>(data);
- runner->__run();
- return NULL;
-}
-
-void ServiceRunner::__run()
-{
- if (!__init()) {
- _E("Starting '%s' failed", __service->getServiceName());
- __release();
- return;
- }
-
- __threadRunning.store(true);
-
- _I(CYAN("Starting '%s'"), __service->getServiceName());
- g_main_loop_run(__mainLoop);
-
- __threadRunning.store(false);
-
- __release();
+ if (__started)
+ __service->onUserDeactivated();
}
bool ServiceRunner::__init()
vtable.get_property = NULL;
vtable.set_property = NULL;
- __mainContext = g_main_context_new();
- IF_FAIL_RETURN_TAG(__mainContext, false, _E, "MainContext creation failed");
-
- g_main_context_push_thread_default(__mainContext);
-
- __mainLoop = g_main_loop_new(__mainContext, FALSE);
- IF_FAIL_RETURN_TAG(__mainLoop, false, _E, "MainLoop creation failed");
-
std::string introspection("<node><interface name='");
introspection += __interface + "'>" + __service->getMethodSpecs() + "</interface></node>";
void ServiceRunner::__release()
{
- _D("Releasing '%s'", __service->getServiceName());
-
for (auto iter = __clients.begin(); iter != __clients.end(); ++iter) {
iter->second.client->onDisconnected();
delete iter->second.client;
if (__nodeInfo)
g_dbus_node_info_unref(__nodeInfo);
-
- if (__mainLoop)
- g_main_loop_unref(__mainLoop);
-
- if (__mainContext)
- g_main_context_unref(__mainContext);
}
void ServiceRunner::__onMethodCalled(GDBusConnection* conn, const gchar* sender,
#ifndef __CONTEXT_SERVICE_RUNNER_H__
#define __CONTEXT_SERVICE_RUNNER_H__
-#include <atomic>
#include <string>
#include <map>
#include <ContextTypes.h>
IService* getService();
private:
- static gpointer __threadFunc(gpointer data);
-
static void __onMethodCalled(GDBusConnection* conn, const gchar* sender,
const gchar* path, const gchar* iface, const gchar* name,
GVariant* param, GDBusMethodInvocation* invocation, gpointer userData);
const gchar* path, const gchar* iface, const gchar* name,
GVariant* param, gpointer userData);
- static gboolean __onUserActivated(gpointer data);
-
- static gboolean __onUserDeactivated(gpointer data);
-
- static gboolean __stopMainLoop(gpointer data);
-
void __onMethodCalled(const std::string& sender,
const std::string& name, GVariant* param, GDBusMethodInvocation* invocation);
- void __run();
bool __init();
void __release();
IService* __service;
bool __started;
- std::atomic_bool __threadRunning;
-
- GMainContext* __mainContext;
- GMainLoop* __mainLoop;
- GThread* __gthread;
GDBusConnection* __connection;
std::string __objPath;