зеркало из https://github.com/mozilla/gecko-dev.git
Bug 830290: Execute DBus send operation in DBus thread r=bent,qdot
The DBus send operation simply sends a DBus message without further processing of replies. If the sender is interested in a reply, the respective serial number can be returned. In this case, the sending operation (and only the sending) is serialized with the calling thread.
This commit is contained in:
Родитель
5c1a06a7d3
Коммит
49b1e5406b
|
@ -19,6 +19,7 @@
|
|||
#include "DBusUtils.h"
|
||||
#include "DBusThread.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "mozilla/Monitor.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
@ -70,6 +71,164 @@ protected:
|
|||
DBusMessageRefPtr mMessage;
|
||||
};
|
||||
|
||||
class DBusConnectionSendSyncRunnable : public DBusConnectionSendRunnableBase
|
||||
{
|
||||
public:
|
||||
bool WaitForCompletion()
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
MonitorAutoLock autoLock(mCompletedMonitor);
|
||||
while (!mCompleted) {
|
||||
mCompletedMonitor.Wait();
|
||||
}
|
||||
return mSuccess;
|
||||
}
|
||||
|
||||
protected:
|
||||
DBusConnectionSendSyncRunnable(DBusConnection* aConnection,
|
||||
DBusMessage* aMessage)
|
||||
: DBusConnectionSendRunnableBase(aConnection, aMessage),
|
||||
mCompletedMonitor("DBusConnectionSendSyncRunnable.mCompleted"),
|
||||
mCompleted(false),
|
||||
mSuccess(false)
|
||||
{ }
|
||||
|
||||
virtual ~DBusConnectionSendSyncRunnable()
|
||||
{ }
|
||||
|
||||
// Call this function at the end of Run() to notify waiting
|
||||
// threads.
|
||||
void Completed(bool aSuccess)
|
||||
{
|
||||
MonitorAutoLock autoLock(mCompletedMonitor);
|
||||
MOZ_ASSERT(!mCompleted);
|
||||
mSuccess = aSuccess;
|
||||
mCompleted = true;
|
||||
mCompletedMonitor.Notify();
|
||||
}
|
||||
|
||||
private:
|
||||
Monitor mCompletedMonitor;
|
||||
bool mCompleted;
|
||||
bool mSuccess;
|
||||
};
|
||||
|
||||
//
|
||||
// Sends a message and returns the message's serial number to the
|
||||
// disaptching thread. Only run it in DBus thread.
|
||||
//
|
||||
class DBusConnectionSendRunnable : public DBusConnectionSendSyncRunnable
|
||||
{
|
||||
public:
|
||||
DBusConnectionSendRunnable(DBusConnection* aConnection,
|
||||
DBusMessage* aMessage,
|
||||
dbus_uint32_t* aSerial)
|
||||
: DBusConnectionSendSyncRunnable(aConnection, aMessage),
|
||||
mSerial(aSerial)
|
||||
{ }
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
dbus_bool_t success = dbus_connection_send(mConnection, mMessage, mSerial);
|
||||
Completed(success == TRUE);
|
||||
|
||||
NS_ENSURE_TRUE(success == TRUE, NS_ERROR_FAILURE);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
~DBusConnectionSendRunnable()
|
||||
{ }
|
||||
|
||||
private:
|
||||
dbus_uint32_t* mSerial;
|
||||
};
|
||||
|
||||
dbus_bool_t
|
||||
dbus_func_send(DBusConnection* aConnection, dbus_uint32_t* aSerial,
|
||||
DBusMessage* aMessage)
|
||||
{
|
||||
nsRefPtr<DBusConnectionSendRunnable> t(
|
||||
new DBusConnectionSendRunnable(aConnection, aMessage, aSerial));
|
||||
MOZ_ASSERT(t);
|
||||
|
||||
nsresult rv = DispatchToDBusThread(t);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
if (aMessage) {
|
||||
dbus_message_unref(aMessage);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (aSerial && !t->WaitForCompletion()) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static dbus_bool_t
|
||||
dbus_func_args_send_valist(DBusConnection* aConnection,
|
||||
dbus_uint32_t* aSerial,
|
||||
const char* aPath,
|
||||
const char* aInterface,
|
||||
const char* aFunction,
|
||||
int aFirstArgType,
|
||||
va_list aArgs)
|
||||
{
|
||||
// Compose the command...
|
||||
DBusMessage* message = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC,
|
||||
aPath,
|
||||
aInterface,
|
||||
aFunction);
|
||||
if (!message) {
|
||||
LOG("Could not allocate D-Bus message object!");
|
||||
goto done;
|
||||
}
|
||||
|
||||
// ... and append arguments.
|
||||
if (!dbus_message_append_args_valist(message, aFirstArgType, aArgs)) {
|
||||
LOG("Could not append argument to method call!");
|
||||
goto done;
|
||||
}
|
||||
|
||||
return dbus_func_send(aConnection, aSerial, message);
|
||||
|
||||
done:
|
||||
if (message) {
|
||||
dbus_message_unref(message);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
dbus_bool_t
|
||||
dbus_func_args_send(DBusConnection* aConnection,
|
||||
dbus_uint32_t* aSerial,
|
||||
const char* aPath,
|
||||
const char* aInterface,
|
||||
const char* aFunction,
|
||||
int aFirstArgType, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, aFirstArgType);
|
||||
|
||||
dbus_bool_t success = dbus_func_args_send_valist(aConnection,
|
||||
aSerial,
|
||||
aPath,
|
||||
aInterface,
|
||||
aFunction,
|
||||
aFirstArgType,
|
||||
args);
|
||||
va_end(args);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
//
|
||||
// Sends a message and executes a callback function for the reply. Only
|
||||
// run it in DBus thread.
|
||||
|
|
|
@ -57,6 +57,17 @@ void log_and_free_dbus_error(DBusError* err,
|
|||
const char* function,
|
||||
DBusMessage* msg = NULL);
|
||||
|
||||
dbus_bool_t dbus_func_send(DBusConnection *aConnection,
|
||||
dbus_uint32_t *aSerial,
|
||||
DBusMessage *aMessage);
|
||||
|
||||
dbus_bool_t dbus_func_args_send(DBusConnection *aConnection,
|
||||
dbus_uint32_t *aSerial,
|
||||
const char *aPath,
|
||||
const char *aInterface,
|
||||
const char *aFunction,
|
||||
int aFirstArgType, ...);
|
||||
|
||||
dbus_bool_t dbus_func_send_async(DBusConnection* conn,
|
||||
DBusMessage* msg,
|
||||
int timeout_ms,
|
||||
|
|
Загрузка…
Ссылка в новой задаче