Bug 853550: Replace Bluetooth command thread, r=echou,gyeh

Starting and stopping Bluetooth support can block the executing thread
for an indefinite amount of time. In most cases these operations are
only performed when Gecko starts and stops, so we don't want to keep
a separate Bluetooth command thread for this.

This patch replaces the Bluetooth command thread by a LazyIdleThread,
which only consumes resources while it executes actual code. After a
timeout period, the LazyIdleThread cleans up its internal state. The
timeout is currently 3 seconds, which has been choosen arbitrarily.

Thanks to bent for helping with the details of LazyIdleThread.
This commit is contained in:
Thomas Zimmermann 2013-08-30 20:18:43 +02:00
parent fc9e658022
commit 26fc503b83
2 changed files with 21 additions and 51 deletions

View File

@ -25,6 +25,7 @@
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
#include "mozilla/ipc/UnixSocket.h"
#include "mozilla/LazyIdleThread.h"
#include "nsContentUtils.h"
#include "nsCxPusher.h"
#include "nsIObserverService.h"
@ -54,6 +55,7 @@
#define PROP_BLUETOOTH_ENABLED "bluetooth.isEnabled"
#define DEFAULT_THREAD_TIMEOUT_MS 3000
#define DEFAULT_SHUTDOWN_TIMER_MS 5000
bool gBluetoothDebugFlag = false;
@ -145,19 +147,8 @@ public:
gBluetoothService->DistributeSignal(signal);
}
if (!mEnabled || gInShutdown) {
// Shut down the command thread if it still exists.
if (gBluetoothService->mBluetoothCommandThread) {
nsCOMPtr<nsIThread> thread;
gBluetoothService->mBluetoothCommandThread.swap(thread);
if (NS_FAILED(thread->Shutdown())) {
NS_WARNING("Failed to shut down the bluetooth command thread!");
}
}
if (gInShutdown) {
gBluetoothService = nullptr;
}
if (gInShutdown) {
gBluetoothService = nullptr;
}
return NS_OK;
@ -461,22 +452,13 @@ BluetoothService::StartStopBluetooth(bool aStart, bool aIsStartup)
return NS_ERROR_FAILURE;
}
if (!mBluetoothCommandThread) {
if (!mBluetoothThread) {
// Don't create a new thread after we've begun shutdown since bluetooth
// can't be running.
return NS_OK;
}
}
nsresult rv;
if (!mBluetoothCommandThread) {
MOZ_ASSERT(!gInShutdown);
rv = NS_NewNamedThread("BluetoothCmd",
getter_AddRefs(mBluetoothCommandThread));
NS_ENSURE_SUCCESS(rv, rv);
}
if (!aStart) {
BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
hfp->Disconnect();
@ -485,8 +467,14 @@ BluetoothService::StartStopBluetooth(bool aStart, bool aIsStartup)
opp->Disconnect();
}
if (!mBluetoothThread) {
mBluetoothThread = new LazyIdleThread(DEFAULT_THREAD_TIMEOUT_MS,
NS_LITERAL_CSTRING("Bluetooth"),
LazyIdleThread::ManualShutdown);
}
nsCOMPtr<nsIRunnable> runnable = new ToggleBtTask(aStart, aIsStartup);
rv = mBluetoothCommandThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
nsresult rv = mBluetoothThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
@ -814,13 +802,3 @@ BluetoothService::Notify(const BluetoothSignal& aData)
OBJECT_TO_JSVAL(obj),
JS::UndefinedValue());
}
void
BluetoothService::DispatchToCommandThread(nsRunnable* aRunnable)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aRunnable);
MOZ_ASSERT(mBluetoothCommandThread);
mBluetoothCommandThread->Dispatch(aRunnable, NS_DISPATCH_NORMAL);
}

View File

@ -307,9 +307,6 @@ public:
void
RemoveObserverFromTable(const nsAString& key);
void
DispatchToCommandThread(nsRunnable* aRunnable);
protected:
BluetoothService()
: mEnabled(false)
@ -387,26 +384,21 @@ protected:
static BluetoothService*
Create();
/**
* Due to the fact that some operations require multiple calls, a
* CommandThread is created that can run blocking, platform-specific calls
* where either no asynchronous equivilent exists, or else where multiple
* asynchronous calls would require excessive runnable bouncing between main
* thread and IO thread.
*
* For instance, when we retrieve an Adapter object, we would like it to come
* with all of its properties filled in and registered as an agent, which
* requires a minimum of 3 calls to platform specific code on some platforms.
*
*/
nsCOMPtr<nsIThread> mBluetoothCommandThread;
typedef nsClassHashtable<nsStringHashKey, BluetoothSignalObserverList >
BluetoothSignalObserverTable;
BluetoothSignalObserverTable mBluetoothSignalObserverTable;
bool mEnabled;
private:
/**
* Due to the fact that the startup and shutdown of the Bluetooth system
* can take an indefinite amount of time, a command thread is created
* that can run blocking calls. The thread is not intended for regular
* Bluetooth operations though.
*/
nsCOMPtr<nsIThread> mBluetoothThread;
};
END_BLUETOOTH_NAMESPACE