Bug 1237414: Switch AsyncCubebOperation to a SharedThreadPool
--- a/dom/media/GraphDriver.cpp
+++ b/dom/media/GraphDriver.cpp
@@ -1,15 +1,17 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <MediaStreamGraphImpl.h>
#include "mozilla/dom/AudioContext.h"
+#include "mozilla/SharedThreadPool.h"
+#include "mozilla/ClearOnShutdown.h"
#include "CubebUtils.h"
#ifdef XP_MACOSX
#include <sys/sysctl.h>
#endif
extern mozilla::LazyLogModule gMediaStreamGraphLog;
#define STREAM_LOG(type, msg) MOZ_LOG(gMediaStreamGraphLog, type, msg)
@@ -25,16 +27,18 @@ extern mozilla::LazyLogModule gMediaStre
#define LIFECYCLE_LOG(...) printf(__VA_ARGS__);printf("\n");
#endif
#else
#define LIFECYCLE_LOG(...)
#endif
namespace mozilla {
+StaticRefPtr<nsIThreadPool> AsyncCubebTask::sThreadPool;
+
struct AutoProfilerUnregisterThread
{
// The empty ctor is used to silence a pre-4.8.0 GCC unused variable warning.
AutoProfilerUnregisterThread()
{
}
~AutoProfilerUnregisterThread()
@@ -464,30 +468,46 @@ AsyncCubebTask::AsyncCubebTask(AudioCall
{
NS_WARN_IF_FALSE(mDriver->mAudioStream || aOperation == INIT, "No audio stream !");
}
AsyncCubebTask::~AsyncCubebTask()
{
}
+/* static */
+nsresult
+AsyncCubebTask::EnsureThread()
+{
+ if (!sThreadPool) {
+ nsCOMPtr<nsIThreadPool> threadPool =
+ SharedThreadPool::Get(NS_LITERAL_CSTRING("CubebOperation"), 1);
+ sThreadPool = threadPool;
+ if (!NS_IsMainThread()) {
+ NS_DispatchToMainThread(NS_NewRunnableFunction([]() -> void {
+ ClearOnShutdown(&sThreadPool);
+ }));
+ } else {
+ ClearOnShutdown(&sThreadPool);
+ }
+
+ const uint32_t kIdleThreadTimeoutMs = 2000;
+
+ nsresult rv = sThreadPool->SetIdleThreadTimeout(PR_MillisecondsToInterval(kIdleThreadTimeoutMs));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ }
+
+ return NS_OK;
+}
+
NS_IMETHODIMP
AsyncCubebTask::Run()
{
- MOZ_ASSERT(mThread);
- if (NS_IsMainThread()) {
- mThread->Shutdown(); // can't shutdown from the thread itself, darn
- // don't null out mThread!
- // See bug 999104. we must hold a ref to the thread across Dispatch()
- // since the internal mthread ref could be released while processing
- // the Dispatch(), and Dispatch/PutEvent itself doesn't hold a ref; it
- // assumes the caller does.
- return NS_OK;
- }
-
MOZ_ASSERT(mDriver);
switch(mOperation) {
case AsyncCubebOperation::INIT: {
LIFECYCLE_LOG("AsyncCubebOperation::INIT driver=%p\n", mDriver.get());
mDriver->Init();
mDriver->CompleteAudioContextOperations(mOperation);
break;
@@ -501,19 +521,17 @@ AsyncCubebTask::Run()
mDriver = nullptr;
mShutdownGrip = nullptr;
break;
}
default:
MOZ_CRASH("Operation not implemented.");
}
- // and now kill this thread
- NS_DispatchToMainThread(this);
-
+ // The thread will kill itself after a bit
return NS_OK;
}
StreamAndPromiseForOperation::StreamAndPromiseForOperation(MediaStream* aStream,
void* aPromise,
dom::AudioContextOperation aOperation)
: mStream(aStream)
, mPromise(aPromise)
--- a/dom/media/GraphDriver.h
+++ b/dom/media/GraphDriver.h
@@ -8,16 +8,18 @@
#include "nsAutoPtr.h"
#include "nsAutoRef.h"
#include "AudioBufferUtils.h"
#include "AudioMixer.h"
#include "AudioSegment.h"
#include "SelfRef.h"
#include "mozilla/Atomics.h"
+#include "mozilla/SharedThreadPool.h"
+#include "mozilla/StaticPtr.h"
struct cubeb_stream;
template <>
class nsAutoRefTraits<cubeb_stream> : public nsPointerRefTraits<cubeb_stream>
{
public:
static void Release(cubeb_stream* aStream) { cubeb_stream_destroy(aStream); }
@@ -544,31 +546,31 @@ private:
class AsyncCubebTask : public nsRunnable
{
public:
AsyncCubebTask(AudioCallbackDriver* aDriver, AsyncCubebOperation aOperation);
nsresult Dispatch()
{
- // Can't add 'this' as the event to run, since mThread may not be set yet
- nsresult rv = NS_NewNamedThread("CubebOperation", getter_AddRefs(mThread));
- if (NS_SUCCEEDED(rv)) {
- // Note: event must not null out mThread!
- rv = mThread->Dispatch(this, NS_DISPATCH_NORMAL);
+ nsresult rv = EnsureThread();
+ if (!NS_FAILED(rv)) {
+ rv = sThreadPool->Dispatch(this, NS_DISPATCH_NORMAL);
}
return rv;
}
protected:
virtual ~AsyncCubebTask();
private:
+ static nsresult EnsureThread();
+
NS_IMETHOD Run() override final;
- nsCOMPtr<nsIThread> mThread;
+ static StaticRefPtr<nsIThreadPool> sThreadPool;
RefPtr<AudioCallbackDriver> mDriver;
AsyncCubebOperation mOperation;
RefPtr<MediaStreamGraphImpl> mShutdownGrip;
};
} // namespace mozilla
#endif // GRAPHDRIVER_H_