author | Kyle Huey <khuey@kylehuey.com> |
Wed, 27 Apr 2016 17:06:05 -0700 | |
changeset 334198 | 30dcf34cfb753d94c79f40bd1af15d3b75e981a5 |
parent 334197 | 5f3d4dd4380f0ac3dc7f9a7bfd66ea534b631475 |
child 334199 | e78a24e7938b2f8ef1e134d13a9b93fa418b2061 |
push id | 6249 |
push user | jlund@mozilla.com |
push date | Mon, 01 Aug 2016 13:59:36 +0000 |
treeherder | mozilla-beta@bad9d4f5bf7e [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | froydnj |
bugs | 1266595 |
milestone | 49.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/ipc/ContentBridgeChild.cpp +++ b/dom/ipc/ContentBridgeChild.cpp @@ -22,24 +22,24 @@ NS_IMPL_ISUPPORTS(ContentBridgeChild, nsIContentChild) ContentBridgeChild::ContentBridgeChild(Transport* aTransport) : mTransport(aTransport) {} ContentBridgeChild::~ContentBridgeChild() { - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new DeleteTask<Transport>(mTransport)); + RefPtr<DeleteTask<Transport>> task = new DeleteTask<Transport>(mTransport); + XRE_GetIOMessageLoop()->PostTask(task.forget()); } void ContentBridgeChild::ActorDestroy(ActorDestroyReason aWhy) { MessageLoop::current()->PostTask( - FROM_HERE, NewRunnableMethod(this, &ContentBridgeChild::DeferredDestroy)); } /*static*/ ContentBridgeChild* ContentBridgeChild::Create(Transport* aTransport, ProcessId aOtherPid) { RefPtr<ContentBridgeChild> bridge = new ContentBridgeChild(aTransport);
--- a/dom/ipc/ContentBridgeParent.cpp +++ b/dom/ipc/ContentBridgeParent.cpp @@ -21,28 +21,28 @@ NS_IMPL_ISUPPORTS(ContentBridgeParent, nsIObserver) ContentBridgeParent::ContentBridgeParent(Transport* aTransport) : mTransport(aTransport) {} ContentBridgeParent::~ContentBridgeParent() { - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new DeleteTask<Transport>(mTransport)); + RefPtr<DeleteTask<Transport>> task = new DeleteTask<Transport>(mTransport); + XRE_GetIOMessageLoop()->PostTask(task.forget()); } void ContentBridgeParent::ActorDestroy(ActorDestroyReason aWhy) { nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService(); if (os) { os->RemoveObserver(this, "content-child-shutdown"); } MessageLoop::current()->PostTask( - FROM_HERE, NewRunnableMethod(this, &ContentBridgeParent::DeferredDestroy)); } /*static*/ ContentBridgeParent* ContentBridgeParent::Create(Transport* aTransport, ProcessId aOtherPid) { RefPtr<ContentBridgeParent> bridge = new ContentBridgeParent(aTransport); @@ -164,17 +164,16 @@ ContentBridgeParent::DeallocPBrowserPare } void ContentBridgeParent::NotifyTabDestroyed() { int32_t numLiveTabs = ManagedPBrowserParent().Count(); if (numLiveTabs == 1) { MessageLoop::current()->PostTask( - FROM_HERE, NewRunnableMethod(this, &ContentBridgeParent::Close)); } } // This implementation is identical to ContentParent::GetCPOWManager but we can't // move it to nsIContentParent because it calls ManagedPJavaScriptParent() which // only exists in PContentParent and PContentBridgeParent. jsipc::CPOWManager*
--- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -1513,17 +1513,17 @@ ContentChild::RecvBidiKeyboardNotify(con // possible implementation of nsIBidiKeyboard is PuppetBidiKeyboard). PuppetBidiKeyboard* bidi = static_cast<PuppetBidiKeyboard*>(nsContentUtils::GetBidiKeyboard()); if (bidi) { bidi->SetIsLangRTL(aIsLangRTL); } return true; } -static CancelableTask* sFirstIdleTask; +static CancelableRunnable* sFirstIdleTask; static void FirstIdle(void) { MOZ_ASSERT(sFirstIdleTask); sFirstIdleTask = nullptr; ContentChild::GetSingleton()->SendFirstIdle(); } @@ -1594,18 +1594,19 @@ ContentChild::RecvPBrowserConstructor(PB os->NotifyObservers(tc, "tab-child-created", nullptr); } static bool hasRunOnce = false; if (!hasRunOnce) { hasRunOnce = true; MOZ_ASSERT(!sFirstIdleTask); - sFirstIdleTask = NewRunnableFunction(FirstIdle); - MessageLoop::current()->PostIdleTask(FROM_HERE, sFirstIdleTask); + RefPtr<CancelableRunnable> firstIdleTask = NewRunnableFunction(FirstIdle); + sFirstIdleTask = firstIdleTask; + MessageLoop::current()->PostIdleTask(firstIdleTask.forget()); // Redo InitProcessAttributes() when the app or browser is really // launching so the attributes will be correct. mID = aCpID; mIsForApp = aIsForApp; mIsForBrowser = aIsForBrowser; InitProcessAttributes(); } @@ -2621,18 +2622,17 @@ ContentChild::RecvAppInit() // BrowserElementChild.js. if (mIsForApp || mIsForBrowser) { PreloadSlowThings(); } #ifdef MOZ_NUWA_PROCESS if (IsNuwaProcess()) { ContentChild::GetSingleton()->RecvGarbageCollect(); - MessageLoop::current()->PostTask( - FROM_HERE, NewRunnableFunction(OnFinishNuwaPreparation)); + MessageLoop::current()->PostTask(NewRunnableFunction(OnFinishNuwaPreparation)); } #endif return true; } bool ContentChild::RecvLastPrivateDocShellDestroyed()
--- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -795,18 +795,17 @@ ContentParent::JoinAllSubprocesses() printf_stderr("There are no live subprocesses."); return; } printf_stderr("Subprocesses are still alive. Doing emergency join.\n"); bool done = false; Monitor monitor("mozilla.dom.ContentParent.JoinAllSubprocesses"); - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, - NewRunnableFunction( + XRE_GetIOMessageLoop()->PostTask(NewRunnableFunction( &ContentParent::JoinProcessesIOThread, &processes, &monitor, &done)); { MonitorAutoLock lock(monitor); while (!done) { lock.Wait(); } } @@ -2175,17 +2174,16 @@ ContentParent::ActorDestroy(ActorDestroy } } } // Destroy any processes created by this ContentParent for(uint32_t i = 0; i < childIDArray.Length(); i++) { ContentParent* cp = cpm->GetContentProcessById(childIDArray[i]); MessageLoop::current()->PostTask( - FROM_HERE, NewRunnableMethod(cp, &ContentParent::ShutDownProcess, SEND_SHUTDOWN_MESSAGE)); } cpm->RemoveContentProcess(this->ChildID()); if (mDriverCrashGuard) { mDriverCrashGuard->NotifyCrashed(); } @@ -2259,17 +2257,16 @@ ContentParent::NotifyTabDestroyed(const // because of popup windows. When the last one closes, shut // us down. ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); nsTArray<TabId> tabIds = cpm->GetTabParentsByProcessId(this->ChildID()); if (tabIds.Length() == 1) { // In the case of normal shutdown, send a shutdown message to child to // allow it to perform shutdown tasks. MessageLoop::current()->PostTask( - FROM_HERE, NewRunnableMethod(this, &ContentParent::ShutDownProcess, SEND_SHUTDOWN_MESSAGE)); } } jsipc::CPOWManager* ContentParent::GetCPOWManager() { @@ -3624,17 +3621,16 @@ ContentParent::KillHard(const char* aRea } if (mSubprocess) { mSubprocess->SetAlreadyDead(); } // EnsureProcessTerminated has responsibilty for closing otherProcessHandle. XRE_GetIOMessageLoop()->PostTask( - FROM_HERE, NewRunnableFunction(&ProcessWatcher::EnsureProcessTerminated, otherProcessHandle, /*force=*/true)); } bool ContentParent::IsPreallocated() const { return mAppManifestURL == MAGIC_PREALLOCATED_APP_MANIFEST_URL;
--- a/dom/ipc/PreallocatedProcessManager.cpp +++ b/dom/ipc/PreallocatedProcessManager.cpp @@ -200,31 +200,29 @@ PreallocatedProcessManagerImpl::Enable() void PreallocatedProcessManagerImpl::AllocateAfterDelay() { if (!mEnabled || mPreallocatedAppProcess) { return; } MessageLoop::current()->PostDelayedTask( - FROM_HERE, NewRunnableMethod(this, &PreallocatedProcessManagerImpl::AllocateOnIdle), Preferences::GetUint("dom.ipc.processPrelaunch.delayMs", DEFAULT_ALLOCATE_DELAY)); } void PreallocatedProcessManagerImpl::AllocateOnIdle() { if (!mEnabled || mPreallocatedAppProcess) { return; } MessageLoop::current()->PostIdleTask( - FROM_HERE, NewRunnableMethod(this, &PreallocatedProcessManagerImpl::AllocateNow)); } void PreallocatedProcessManagerImpl::AllocateNow() { if (!mEnabled || mPreallocatedAppProcess) { return; @@ -240,20 +238,20 @@ PreallocatedProcessManagerImpl::Schedule { MOZ_ASSERT(NS_IsMainThread()); if (mPreallocateAppProcessTask) { // Make sure there is only one request running. return; } - mPreallocateAppProcessTask = NewRunnableMethod( + RefPtr<CancelableTask> task = NewRunnableMethod( this, &PreallocatedProcessManagerImpl::DelayedNuwaFork); - MessageLoop::current()->PostDelayedTask( - FROM_HERE, mPreallocateAppProcessTask, + mPreallocateAppProcessTask = task; + MessageLoop::current()->PostDelayedTask(task.forget(), Preferences::GetUint("dom.ipc.processPrelaunch.delayMs", DEFAULT_ALLOCATE_DELAY)); } void PreallocatedProcessManagerImpl::DelayedNuwaFork() { MOZ_ASSERT(NS_IsMainThread());
--- a/dom/ipc/ProcessHangMonitor.cpp +++ b/dom/ipc/ProcessHangMonitor.cpp @@ -260,17 +260,18 @@ HangMonitorChild::HangMonitorChild(Proce { MOZ_RELEASE_ASSERT(NS_IsMainThread()); } HangMonitorChild::~HangMonitorChild() { // For some reason IPDL doesn't automatically delete the channel for a // bridged protocol (bug 1090570). So we have to do it ourselves. - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new DeleteTask<Transport>(GetTransport())); + RefPtr<DeleteTask<Transport>> task = new DeleteTask<Transport>(GetTransport()); + XRE_GetIOMessageLoop()->PostTask(task.forget()); MOZ_RELEASE_ASSERT(NS_IsMainThread()); MOZ_ASSERT(sInstance == this); sInstance = nullptr; } void HangMonitorChild::Shutdown() @@ -298,17 +299,16 @@ HangMonitorChild::ActorDestroy(ActorDest { MOZ_RELEASE_ASSERT(MessageLoop::current() == MonitorLoop()); mIPCOpen = false; // We use a task here to ensure that IPDL is finished with this // HangMonitorChild before it gets deleted on the main thread. MonitorLoop()->PostTask( - FROM_HERE, NewRunnableMethod(this, &HangMonitorChild::ShutdownOnThread)); } bool HangMonitorChild::RecvTerminateScript() { MOZ_RELEASE_ASSERT(MessageLoop::current() == MonitorLoop()); @@ -386,17 +386,16 @@ HangMonitorChild::NotifySlowScript(nsITa TabId id; if (aTabChild) { RefPtr<TabChild> tabChild = static_cast<TabChild*>(aTabChild); id = tabChild->GetTabId(); } nsAutoCString filename(aFileName); MonitorLoop()->PostTask( - FROM_HERE, NewRunnableMethod(this, &HangMonitorChild::NotifySlowScriptAsync, id, filename, aLineNo)); return SlowScriptAction::Continue; } bool HangMonitorChild::IsDebuggerStartupComplete() { @@ -417,17 +416,16 @@ HangMonitorChild::NotifyPluginHang(uint3 { // main thread in the child MOZ_RELEASE_ASSERT(NS_IsMainThread()); mSentReport = true; // bounce to background thread MonitorLoop()->PostTask( - FROM_HERE, NewRunnableMethod(this, &HangMonitorChild::NotifyPluginHangAsync, aPluginId)); } void HangMonitorChild::NotifyPluginHangAsync(uint32_t aPluginId) { @@ -443,17 +441,16 @@ HangMonitorChild::NotifyPluginHangAsync( void HangMonitorChild::ClearHang() { MOZ_ASSERT(NS_IsMainThread()); if (mSentReport) { // bounce to background thread MonitorLoop()->PostTask( - FROM_HERE, NewRunnableMethod(this, &HangMonitorChild::ClearHangAsync)); MonitorAutoLock lock(mMonitor); mSentReport = false; mTerminateScript = false; mStartDebugger = false; mFinishedStartingDebugger = false; } @@ -482,17 +479,18 @@ HangMonitorParent::HangMonitorParent(Pro MOZ_RELEASE_ASSERT(NS_IsMainThread()); mReportHangs = mozilla::Preferences::GetBool("dom.ipc.reportProcessHangs", false); } HangMonitorParent::~HangMonitorParent() { // For some reason IPDL doesn't automatically delete the channel for a // bridged protocol (bug 1090570). So we have to do it ourselves. - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new DeleteTask<Transport>(GetTransport())); + RefPtr<DeleteTask<Transport>> task = new DeleteTask<Transport>(GetTransport()); + XRE_GetIOMessageLoop()->PostTask(task.forget()); #ifdef MOZ_CRASHREPORTER MutexAutoLock lock(mBrowserCrashDumpHashLock); for (auto iter = mBrowserCrashDumpIds.Iter(); !iter.Done(); iter.Next()) { nsString crashId = iter.UserData(); if (!crashId.IsEmpty()) { CrashReporter::DeleteMinidumpFilesForID(crashId); @@ -509,17 +507,16 @@ HangMonitorParent::Shutdown() MonitorAutoLock lock(mMonitor); if (mProcess) { mProcess->Clear(); mProcess = nullptr; } MonitorLoop()->PostTask( - FROM_HERE, NewRunnableMethod(this, &HangMonitorParent::ShutdownOnThread)); while (!mShutdownDone) { mMonitor.Wait(); } } void @@ -831,17 +828,16 @@ HangMonitoredProcess::TerminateScript() return NS_ERROR_UNEXPECTED; } if (!mActor) { return NS_ERROR_UNEXPECTED; } ProcessHangMonitor::Get()->MonitorLoop()->PostTask( - FROM_HERE, NewRunnableMethod(mActor, &HangMonitorParent::TerminateScript)); return NS_OK; } NS_IMETHODIMP HangMonitoredProcess::BeginStartingDebugger() { MOZ_RELEASE_ASSERT(NS_IsMainThread()); @@ -849,17 +845,16 @@ HangMonitoredProcess::BeginStartingDebug return NS_ERROR_UNEXPECTED; } if (!mActor) { return NS_ERROR_UNEXPECTED; } ProcessHangMonitor::Get()->MonitorLoop()->PostTask( - FROM_HERE, NewRunnableMethod(mActor, &HangMonitorParent::BeginStartingDebugger)); return NS_OK; } NS_IMETHODIMP HangMonitoredProcess::EndStartingDebugger() { MOZ_RELEASE_ASSERT(NS_IsMainThread()); @@ -867,17 +862,16 @@ HangMonitoredProcess::EndStartingDebugge return NS_ERROR_UNEXPECTED; } if (!mActor) { return NS_ERROR_UNEXPECTED; } ProcessHangMonitor::Get()->MonitorLoop()->PostTask( - FROM_HERE, NewRunnableMethod(mActor, &HangMonitorParent::EndStartingDebugger)); return NS_OK; } NS_IMETHODIMP HangMonitoredProcess::TerminatePlugin() { MOZ_RELEASE_ASSERT(NS_IsMainThread()); @@ -1047,34 +1041,32 @@ mozilla::CreateHangMonitorParent(Content ProcessHangMonitor* monitor = ProcessHangMonitor::GetOrCreate(); HangMonitorParent* parent = new HangMonitorParent(monitor); HangMonitoredProcess* process = new HangMonitoredProcess(parent, aContentParent); parent->SetProcess(process); monitor->MonitorLoop()->PostTask( - FROM_HERE, NewRunnableMethod(parent, &HangMonitorParent::Open, aTransport, aOtherPid, XRE_GetIOMessageLoop())); return parent; } PProcessHangMonitorChild* mozilla::CreateHangMonitorChild(mozilla::ipc::Transport* aTransport, base::ProcessId aOtherPid) { MOZ_RELEASE_ASSERT(NS_IsMainThread()); ProcessHangMonitor* monitor = ProcessHangMonitor::GetOrCreate(); HangMonitorChild* child = new HangMonitorChild(monitor); monitor->MonitorLoop()->PostTask( - FROM_HERE, NewRunnableMethod(child, &HangMonitorChild::Open, aTransport, aOtherPid, XRE_GetIOMessageLoop())); return child; } MessageLoop* ProcessHangMonitor::MonitorLoop()
--- a/dom/media/MediaManager.cpp +++ b/dom/media/MediaManager.cpp @@ -241,17 +241,17 @@ HostHasPermission(nsIURI &docURI) } while (end < domainWhiteList.Length()); return false; } // Generic class for running long media operations like Start off the main // thread, and then (because nsDOMMediaStreams aren't threadsafe), // ProxyReleases mStream since it's cycle collected. -class MediaOperationTask : public Task +class MediaOperationTask : public Runnable { public: // so we can send Stop without AddRef()ing from the MSG thread MediaOperationTask(MediaOperation aType, GetUserMediaCallbackMediaStreamListener* aListener, DOMMediaStream* aStream, OnTracksAvailableCallback* aOnTracksAvailableCallback, AudioDevice* aAudioDevice, @@ -275,45 +275,45 @@ public: ~MediaOperationTask() { // MediaStreams can be released on any thread. } void ReturnCallbackError(nsresult rv, const char* errorLog); - void - Run() + NS_IMETHOD + Run() override { SourceMediaStream *source = mListener->GetSourceStream(); // No locking between these is required as all the callbacks for the // same MediaStream will occur on the same thread. if (!source) // means the stream was never Activated() - return; + return NS_OK; switch (mType) { case MEDIA_START: { NS_ASSERTION(!NS_IsMainThread(), "Never call on main thread"); nsresult rv; if (mAudioDevice) { rv = mAudioDevice->GetSource()->Start(source, kAudioTrack, mListener->GetPrincipalHandle()); if (NS_FAILED(rv)) { ReturnCallbackError(rv, "Starting audio failed"); - return; + return NS_OK; } } if (mVideoDevice) { rv = mVideoDevice->GetSource()->Start(source, kVideoTrack, mListener->GetPrincipalHandle()); if (NS_FAILED(rv)) { ReturnCallbackError(rv, "Starting video failed"); - return; + return NS_OK; } } // Start() queued the tracks to be added synchronously to avoid races source->FinishAddTracks(); source->SetPullEnabled(true); source->AdvanceKnownTracksTime(STREAM_TIME_MAX); @@ -372,16 +372,18 @@ public: } } break; default: MOZ_ASSERT(false,"invalid MediaManager operation"); break; } + + return NS_OK; } private: MediaOperation mType; RefPtr<DOMMediaStream> mStream; nsAutoPtr<OnTracksAvailableCallback> mOnTracksAvailableCallback; RefPtr<AudioDevice> mAudioDevice; // threadsafe RefPtr<VideoDevice> mVideoDevice; // threadsafe @@ -969,21 +971,22 @@ public: // Note: includes JS callbacks; must be released on MainThread TracksAvailableCallback* tracksAvailableCallback = new TracksAvailableCallback(mManager, mOnSuccess, mWindowID, domStream); // Dispatch to the media thread to ask it to start the sources, // because that can take a while. // Pass ownership of domStream to the MediaOperationTask // to ensure it's kept alive until the MediaOperationTask runs (at least). - MediaManager::PostTask(FROM_HERE, + RefPtr<Runnable> mediaOperation = new MediaOperationTask(MEDIA_START, mListener, domStream, tracksAvailableCallback, mAudioDevice, mVideoDevice, - false, mWindowID, mOnFailure.forget())); + false, mWindowID, mOnFailure.forget()); + MediaManager::PostTask(mediaOperation.forget()); // We won't need mOnFailure now. mOnFailure = nullptr; if (!MediaManager::IsPrivateBrowsing(window)) { // Call GetOriginKey again, this time w/persist = true, to promote // deviceIds to persistent, in case they're not already. Fire'n'forget. RefPtr<Pledge<nsCString>> p = media::GetOriginKey(mOrigin, false, true); } @@ -1063,18 +1066,17 @@ MediaManager::SelectSettings( { MOZ_ASSERT(NS_IsMainThread()); RefPtr<PledgeChar> p = new PledgeChar(); uint32_t id = mOutstandingCharPledges.Append(*p); // Algorithm accesses device capabilities code and must run on media thread. // Modifies passed-in aSources. - MediaManager::PostTask(FROM_HERE, NewTaskFrom([id, aConstraints, - aSources]() mutable { + MediaManager::PostTask(NewTaskFrom([id, aConstraints, aSources]() mutable { auto& sources = **aSources; // Since the advanced part of the constraints algorithm needs to know when // a candidate set is overconstrained (zero members), we must split up the // list into videos and audios, and put it back together again at the end. nsTArray<RefPtr<VideoDevice>> videos; nsTArray<RefPtr<AudioDevice>> audios; @@ -1100,37 +1102,37 @@ MediaManager::SelectSettings( } if (audios.Length() && IsOn(aConstraints.mAudio)) { badConstraint = MediaConstraintsHelper::SelectSettings( GetInvariant(aConstraints.mAudio), audios); for (auto& audio : audios) { sources.AppendElement(audio); } } - NS_DispatchToMainThread(do_AddRef(NewRunnableFrom([id, badConstraint]() mutable { + NS_DispatchToMainThread(NewRunnableFrom([id, badConstraint]() mutable { RefPtr<MediaManager> mgr = MediaManager_GetInstance(); RefPtr<PledgeChar> p = mgr->mOutstandingCharPledges.Remove(id); if (p) { p->Resolve(badConstraint); } return NS_OK; - }))); + })); })); return p.forget(); } /** * Runs on a seperate thread and is responsible for enumerating devices. * Depending on whether a picture or stream was asked for, either * ProcessGetUserMedia is called, and the results are sent back to the DOM. * * Do not run this on the main thread. The success and error callbacks *MUST* * be dispatched on the main thread! */ -class GetUserMediaTask : public Task +class GetUserMediaTask : public Runnable { public: GetUserMediaTask( const MediaStreamConstraints& aConstraints, already_AddRefed<nsIDOMGetUserMediaSuccessCallback> aOnSuccess, already_AddRefed<nsIDOMGetUserMediaErrorCallback> aOnFailure, uint64_t aWindowID, GetUserMediaCallbackMediaStreamListener *aListener, MediaEnginePrefs &aPrefs, @@ -1163,18 +1165,18 @@ public: MOZ_ASSERT(!mOnSuccess); MOZ_ASSERT(!mOnFailure); NS_DispatchToMainThread(runnable.forget()); // Do after ErrorCallbackRunnable Run()s, as it checks active window list NS_DispatchToMainThread(do_AddRef(new GetUserMediaListenerRemove(mWindowID, mListener))); } - void - Run() + NS_IMETHOD + Run() override { MOZ_ASSERT(!NS_IsMainThread()); MOZ_ASSERT(mOnSuccess); MOZ_ASSERT(mOnFailure); MOZ_ASSERT(mDeviceChosen); // Allocate a video or audio device and return a MediaStream via // a GetUserMediaStreamRunnable. @@ -1183,43 +1185,44 @@ public: if (mAudioDevice) { rv = mAudioDevice->Allocate(GetInvariant(mConstraints.mAudio), mPrefs, mOrigin); if (NS_FAILED(rv)) { LOG(("Failed to allocate audiosource %d",rv)); Fail(NS_LITERAL_STRING("SourceUnavailableError"), NS_LITERAL_STRING("Failed to allocate audiosource")); - return; + return NS_OK; } } if (mVideoDevice) { rv = mVideoDevice->Allocate(GetInvariant(mConstraints.mVideo), mPrefs, mOrigin); if (NS_FAILED(rv)) { LOG(("Failed to allocate videosource %d\n",rv)); if (mAudioDevice) { mAudioDevice->GetSource()->Deallocate(); } Fail(NS_LITERAL_STRING("SourceUnavailableError"), NS_LITERAL_STRING("Failed to allocate videosource")); - return; + return NS_OK; } } PeerIdentity* peerIdentity = nullptr; if (!mConstraints.mPeerIdentity.IsEmpty()) { peerIdentity = new PeerIdentity(mConstraints.mPeerIdentity); } NS_DispatchToMainThread(do_AddRef( new GetUserMediaStreamRunnable(mOnSuccess, mOnFailure, mWindowID, mListener, mOrigin, mAudioDevice, mVideoDevice, peerIdentity))); MOZ_ASSERT(!mOnSuccess); MOZ_ASSERT(!mOnFailure); + return NS_OK; } nsresult Denied(const nsAString& aName, const nsAString& aMessage = EmptyString()) { MOZ_ASSERT(mOnSuccess); MOZ_ASSERT(mOnFailure); @@ -1301,17 +1304,17 @@ public: // This object must take ownership of task GetUserMediaRunnableWrapper(GetUserMediaTask* task) : mTask(task) { } ~GetUserMediaRunnableWrapper() { } - NS_IMETHOD Run() { + NS_IMETHOD Run() override { mTask->Run(); return NS_OK; } private: nsAutoPtr<GetUserMediaTask> mTask; }; #endif @@ -1346,20 +1349,20 @@ MediaManager::EnumerateRawDevices(uint64 } } if (!aFake) { // Fake tracks only make sense when we have a fake stream. aFakeTracks = false; } - MediaManager::PostTask(FROM_HERE, NewTaskFrom([id, aWindowId, audioLoopDev, - videoLoopDev, aVideoType, - aAudioType, aFake, - aFakeTracks]() mutable { + MediaManager::PostTask(NewTaskFrom([id, aWindowId, audioLoopDev, + videoLoopDev, aVideoType, + aAudioType, aFake, + aFakeTracks]() mutable { // Only enumerate what's asked for, and only fake cams and mics. bool hasVideo = aVideoType != MediaSourceEnum::Other; bool hasAudio = aAudioType != MediaSourceEnum::Other; bool fakeCams = aFake && aVideoType == MediaSourceEnum::Camera; bool fakeMics = aFake && aAudioType == MediaSourceEnum::Microphone; RefPtr<MediaEngine> fakeBackend, realBackend; if (fakeCams || fakeMics) { @@ -1384,28 +1387,28 @@ MediaManager::EnumerateRawDevices(uint64 nsTArray<RefPtr<AudioDevice>> audios; GetSources(fakeMics? fakeBackend : realBackend, aAudioType, &MediaEngine::EnumerateAudioDevices, audios, audioLoopDev); for (auto& source : audios) { result->AppendElement(source); } } SourceSet* handoff = result.release(); - NS_DispatchToMainThread(do_AddRef(NewRunnableFrom([id, handoff]() mutable { + NS_DispatchToMainThread(NewRunnableFrom([id, handoff]() mutable { UniquePtr<SourceSet> result(handoff); // grab result RefPtr<MediaManager> mgr = MediaManager_GetInstance(); if (!mgr) { return NS_OK; } RefPtr<PledgeSourceSet> p = mgr->mOutstandingPledges.Remove(id); if (p) { p->Resolve(result.release()); } return NS_OK; - }))); + })); })); return p.forget(); } MediaManager::MediaManager() : mMediaThread(nullptr) , mBackend(nullptr) { mPrefs.mFreq = 1000; // 1KHz test tone @@ -1593,26 +1596,29 @@ MediaManager::StartupInit() free(pAdapterInfo); } } #endif } /* static */ void -MediaManager::PostTask(const tracked_objects::Location& from_here, Task* task) +MediaManager::PostTask(already_AddRefed<Runnable> task) { if (sInShutdown) { // Can't safely delete task here since it may have items with specific // thread-release requirements. + // XXXkhuey well then who is supposed to delete it?! We don't signal + // that we failed ... + MOZ_CRASH(); return; } NS_ASSERTION(Get(), "MediaManager singleton?"); NS_ASSERTION(Get()->mMediaThread, "No thread yet"); - Get()->mMediaThread->message_loop()->PostTask(from_here, task); + Get()->mMediaThread->message_loop()->PostTask(Move(task)); } /* static */ nsresult MediaManager::NotifyRecordingStatusChange(nsPIDOMWindowInner* aWindow, const nsString& aMsg, const bool& aIsAudio, const bool& aIsVideo) { @@ -2118,21 +2124,21 @@ MediaManager::GetUserMedia(nsPIDOMWindow rv = devicesCopy->AppendElement(device); if (NS_WARN_IF(NS_FAILED(rv))) { return; } } } // Pass callbacks and MediaStreamListener along to GetUserMediaTask. - nsAutoPtr<GetUserMediaTask> task (new GetUserMediaTask(c, onSuccess.forget(), - onFailure.forget(), - windowID, listener, - prefs, origin, - devices->release())); + RefPtr<GetUserMediaTask> task (new GetUserMediaTask(c, onSuccess.forget(), + onFailure.forget(), + windowID, listener, + prefs, origin, + devices->release())); // Store the task w/callbacks. mActiveCallbacks.Put(callID, task.forget()); // Add a WindowID cross-reference so OnNavigation can tear things down nsTArray<nsString>* array; if (!mCallIds.Get(windowID, &array)) { array = new nsTArray<nsString>(); mCallIds.Put(windowID, array); @@ -2370,19 +2376,19 @@ MediaManager::GetUserMediaDevices(nsPIDO // Ignore passed-in constraints, instead locate + return already-constrained list. nsTArray<nsString>* callIDs; if (!mCallIds.Get(aWindowId, &callIDs)) { return NS_ERROR_UNEXPECTED; } for (auto& callID : *callIDs) { - GetUserMediaTask* task; + RefPtr<GetUserMediaTask> task; if (!aCallID.Length() || aCallID == callID) { - if (mActiveCallbacks.Get(callID, &task)) { + if (mActiveCallbacks.Get(callID, getter_AddRefs(task))) { nsCOMPtr<nsIWritableVariant> array = MediaManager_ToJSArray(*task->mSourceSet); onSuccess->OnSuccess(array); return NS_OK; } } } return NS_ERROR_UNEXPECTED; } @@ -2611,25 +2617,25 @@ MediaManager::Shutdown() mCallIds.Clear(); #ifdef MOZ_WEBRTC StopWebRtcLog(); #endif // Because mMediaThread is not an nsThread, we must dispatch to it so it can // clean up BackgroundChild. Continue stopping thread once this is done. - class ShutdownTask : public Task + class ShutdownTask : public Runnable { public: ShutdownTask(MediaManager* aManager, - Runnable* aReply) + already_AddRefed<Runnable> aReply) : mManager(aManager) , mReply(aReply) {} private: - void + NS_IMETHOD Run() override { LOG(("MediaManager Thread Shutdown")); MOZ_ASSERT(MediaManager::IsInMediaThread()); // Must shutdown backend on MediaManager thread, since that's where we started it from! { if (mManager->mBackend) { mManager->mBackend->Shutdown(); // ok to invoke multiple times @@ -2637,49 +2643,52 @@ MediaManager::Shutdown() } mozilla::ipc::BackgroundChild::CloseForCurrentThread(); // must explicitly do this before dispatching the reply, since the reply may kill us with Stop() mManager->mBackend = nullptr; // last reference, will invoke Shutdown() again if (NS_FAILED(NS_DispatchToMainThread(mReply.forget()))) { LOG(("Will leak thread: DispatchToMainthread of reply runnable failed in MediaManager shutdown")); } + + return NS_OK; } RefPtr<MediaManager> mManager; RefPtr<Runnable> mReply; }; // Post ShutdownTask to execute on mMediaThread and pass in a lambda // callback to be executed back on this thread once it is done. // // The lambda callback "captures" the 'this' pointer for member access. // This is safe since this is guaranteed to be here since sSingleton isn't // cleared until the lambda function clears it. // note that this == sSingleton RefPtr<MediaManager> that(sSingleton); // Release the backend (and call Shutdown()) from within the MediaManager thread // Don't use MediaManager::PostTask() because we're sInShutdown=true here! - mMediaThread->message_loop()->PostTask(FROM_HERE, new ShutdownTask(this, + RefPtr<ShutdownTask> shutdown = new ShutdownTask(this, media::NewRunnableFrom([this, that]() mutable { LOG(("MediaManager shutdown lambda running, releasing MediaManager singleton and thread")); if (mMediaThread) { mMediaThread->Stop(); } // Remove async shutdown blocker nsCOMPtr<nsIAsyncShutdownClient> shutdownPhase = GetShutdownPhase(); shutdownPhase->RemoveBlocker(sSingleton->mShutdownBlocker); // we hold a ref to 'that' which is the same as sSingleton sSingleton = nullptr; return NS_OK; - }))); + })); + mMediaThread->message_loop()->PostTask(shutdown.forget()); } nsresult MediaManager::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData) { MOZ_ASSERT(NS_IsMainThread()); @@ -2692,18 +2701,18 @@ MediaManager::Observe(nsISupports* aSubj } } else if (!strcmp(aTopic, "last-pb-context-exited")) { // Clear memory of private-browsing-specific deviceIds. Fire and forget. media::SanitizeOriginKeys(0, true); return NS_OK; } else if (!strcmp(aTopic, "getUserMedia:privileged:allow") || !strcmp(aTopic, "getUserMedia:response:allow")) { nsString key(aData); - nsAutoPtr<GetUserMediaTask> task; - mActiveCallbacks.RemoveAndForget(key, task); + RefPtr<GetUserMediaTask> task; + mActiveCallbacks.Remove(key, getter_AddRefs(task)); if (!task) { return NS_OK; } if (aSubject) { // A particular device or devices were chosen by the user. // NOTE: does not allow setting a device to null; assumes nullptr nsCOMPtr<nsISupportsArray> array(do_QueryInterface(aSubject)); @@ -2740,33 +2749,33 @@ MediaManager::Observe(nsISupports* aSubj } } } if (sInShutdown) { return task->Denied(NS_LITERAL_STRING("In shutdown")); } // Reuse the same thread to save memory. - MediaManager::PostTask(FROM_HERE, task.forget()); + MediaManager::PostTask(task.forget()); return NS_OK; } else if (!strcmp(aTopic, "getUserMedia:response:deny")) { nsString errorMessage(NS_LITERAL_STRING("SecurityError")); if (aSubject) { nsCOMPtr<nsISupportsString> msg(do_QueryInterface(aSubject)); MOZ_ASSERT(msg); msg->GetData(errorMessage); if (errorMessage.IsEmpty()) errorMessage.AssignLiteral(MOZ_UTF16("InternalError")); } nsString key(aData); - nsAutoPtr<GetUserMediaTask> task; - mActiveCallbacks.RemoveAndForget(key, task); + RefPtr<GetUserMediaTask> task; + mActiveCallbacks.Remove(key, getter_AddRefs(task)); if (task) { task->Denied(errorMessage); } return NS_OK; } else if (!strcmp(aTopic, "getUserMedia:revoke")) { nsresult rv; // may be windowid or screen:windowid @@ -3076,22 +3085,23 @@ GetUserMediaCallbackMediaStreamListener: if (mStopped) { return; } // We can't take a chance on blocking here, so proxy this to another // thread. // Pass a ref to us (which is threadsafe) so it can query us for the // source stream info. - MediaManager::PostTask(FROM_HERE, + RefPtr<MediaOperationTask> mediaOperation = new MediaOperationTask(MEDIA_STOP, this, nullptr, nullptr, !mAudioStopped ? mAudioDevice.get() : nullptr, !mVideoStopped ? mVideoDevice.get() : nullptr, - false, mWindowID, nullptr)); + false, mWindowID, nullptr); + MediaManager::PostTask(mediaOperation.forget()); mStopped = mAudioStopped = mVideoStopped = true; } // Doesn't kill audio void GetUserMediaCallbackMediaStreamListener::StopSharing() { MOZ_ASSERT(NS_IsMainThread()); @@ -3141,19 +3151,19 @@ GetUserMediaCallbackMediaStreamListener: p->Resolve(false); return p.forget(); } RefPtr<MediaManager> mgr = MediaManager::GetInstance(); uint32_t id = mgr->mOutstandingVoidPledges.Append(*p); uint64_t windowId = aWindow->WindowID(); - MediaManager::PostTask(FROM_HERE, NewTaskFrom([id, windowId, - audioDevice, videoDevice, - aConstraints]() mutable { + MediaManager::PostTask(NewTaskFrom([id, windowId, + audioDevice, videoDevice, + aConstraints]() mutable { MOZ_ASSERT(MediaManager::IsInMediaThread()); RefPtr<MediaManager> mgr = MediaManager::GetInstance(); const char* badConstraint = nullptr; nsresult rv = NS_OK; if (audioDevice) { rv = audioDevice->Restart(aConstraints, mgr->mPrefs); if (rv == NS_ERROR_NOT_AVAILABLE) { @@ -3166,18 +3176,18 @@ GetUserMediaCallbackMediaStreamListener: rv = videoDevice->Restart(aConstraints, mgr->mPrefs); if (rv == NS_ERROR_NOT_AVAILABLE) { nsTArray<RefPtr<VideoDevice>> videos; videos.AppendElement(videoDevice); badConstraint = MediaConstraintsHelper::SelectSettings(aConstraints, videos); } } - NS_DispatchToMainThread(do_AddRef(NewRunnableFrom([id, windowId, rv, - badConstraint]() mutable { + NS_DispatchToMainThread(NewRunnableFrom([id, windowId, rv, + badConstraint]() mutable { MOZ_ASSERT(NS_IsMainThread()); RefPtr<MediaManager> mgr = MediaManager_GetInstance(); if (!mgr) { return NS_OK; } RefPtr<PledgeVoid> p = mgr->mOutstandingVoidPledges.Remove(id); if (p) { if (NS_SUCCEEDED(rv)) { @@ -3199,17 +3209,17 @@ GetUserMediaCallbackMediaStreamListener: new MediaStreamError(window->AsInner(), NS_LITERAL_STRING("InternalError")); p->Reject(error); } } } } return NS_OK; - }))); + })); })); return p.forget(); } // Stop backend for track void GetUserMediaCallbackMediaStreamListener::StopTrack(TrackID aTrackID) @@ -3236,22 +3246,23 @@ GetUserMediaCallbackMediaStreamListener: } if ((stopAudio || mAudioStopped || !mAudioDevice) && (stopVideo || mVideoStopped || !mVideoDevice)) { Stop(); return; } - MediaManager::PostTask(FROM_HERE, + RefPtr<MediaOperationTask> mediaOperation = new MediaOperationTask(MEDIA_STOP_TRACK, this, nullptr, nullptr, stopAudio ? mAudioDevice.get() : nullptr, stopVideo ? mVideoDevice.get() : nullptr, - false , mWindowID, nullptr)); + false , mWindowID, nullptr); + MediaManager::PostTask(mediaOperation.forget()); mAudioStopped |= stopAudio; mVideoStopped |= stopVideo; } void GetUserMediaCallbackMediaStreamListener::NotifyFinished() { MOZ_ASSERT(NS_IsMainThread()); @@ -3266,21 +3277,22 @@ GetUserMediaCallbackMediaStreamListener: } } // Called from the MediaStreamGraph thread void GetUserMediaCallbackMediaStreamListener::NotifyDirectListeners(MediaStreamGraph* aGraph, bool aHasListeners) { - MediaManager::PostTask(FROM_HERE, + RefPtr<MediaOperationTask> mediaOperation = new MediaOperationTask(MEDIA_DIRECT_LISTENERS, this, nullptr, nullptr, mAudioDevice, mVideoDevice, - aHasListeners, mWindowID, nullptr)); + aHasListeners, mWindowID, nullptr); + MediaManager::PostTask(mediaOperation.forget()); } // this can be in response to our own RemoveListener() (via ::Remove()), or // because the DOM GC'd the DOMLocalMediaStream/etc we're attached to. void GetUserMediaCallbackMediaStreamListener::NotifyRemoved() { MOZ_ASSERT(NS_IsMainThread());
--- a/dom/media/MediaManager.h +++ b/dom/media/MediaManager.h @@ -419,17 +419,17 @@ public: static already_AddRefed<MediaManager> GetInstance(); // NOTE: never Dispatch(....,NS_DISPATCH_SYNC) to the MediaManager // thread from the MainThread, as we NS_DISPATCH_SYNC to MainThread // from MediaManager thread. static MediaManager* Get(); static MediaManager* GetIfExists(); static void StartupInit(); - static void PostTask(const tracked_objects::Location& from_here, Task* task); + static void PostTask(already_AddRefed<Runnable> task); #ifdef DEBUG static bool IsInMediaThread(); #endif static bool Exists() { return !!sSingleton; } @@ -531,17 +531,17 @@ private: void IterateWindowListeners(nsPIDOMWindowInner *aWindow, WindowListenerCallback aCallback, void *aData); void StopMediaStreams(); // ONLY access from MainThread so we don't need to lock WindowTable mActiveWindows; - nsClassHashtable<nsStringHashKey, GetUserMediaTask> mActiveCallbacks; + nsRefPtrHashtable<nsStringHashKey, GetUserMediaTask> mActiveCallbacks; nsClassHashtable<nsUint64HashKey, nsTArray<nsString>> mCallIds; // Always exists nsAutoPtr<base::Thread> mMediaThread; nsCOMPtr<nsIAsyncShutdownBlocker> mShutdownBlocker; // ONLY accessed from MediaManagerThread RefPtr<MediaEngine> mBackend;
--- a/dom/media/gmp/GMPChild.cpp +++ b/dom/media/gmp/GMPChild.cpp @@ -620,18 +620,19 @@ GMPChild::AllocPGMPContentChild(Transpor void GMPChild::GMPContentChildActorDestroy(GMPContentChild* aGMPContentChild) { for (uint32_t i = mGMPContentChildren.Length(); i > 0; i--) { UniquePtr<GMPContentChild>& toDestroy = mGMPContentChildren[i - 1]; if (toDestroy.get() == aGMPContentChild) { SendPGMPContentChildDestroyed(); - MessageLoop::current()->PostTask(FROM_HERE, - new DeleteTask<GMPContentChild>(toDestroy.release())); + RefPtr<DeleteTask<GMPContentChild>> task = + new DeleteTask<GMPContentChild>(toDestroy.release()); + MessageLoop::current()->PostTask(task.forget()); mGMPContentChildren.RemoveElementAt(i - 1); break; } } } } // namespace gmp } // namespace mozilla
--- a/dom/media/gmp/GMPContentChild.cpp +++ b/dom/media/gmp/GMPContentChild.cpp @@ -17,18 +17,18 @@ GMPContentChild::GMPContentChild(GMPChil : mGMPChild(aChild) { MOZ_COUNT_CTOR(GMPContentChild); } GMPContentChild::~GMPContentChild() { MOZ_COUNT_DTOR(GMPContentChild); - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, - new DeleteTask<Transport>(GetTransport())); + RefPtr<DeleteTask<Transport>> task = new DeleteTask<Transport>(GetTransport()); + XRE_GetIOMessageLoop()->PostTask(task.forget()); } MessageLoop* GMPContentChild::GMPMessageLoop() { return mGMPChild->GMPMessageLoop(); }
--- a/dom/media/gmp/GMPContentParent.cpp +++ b/dom/media/gmp/GMPContentParent.cpp @@ -38,18 +38,18 @@ GMPContentParent::GMPContentParent(GMPPa if (mParent) { SetDisplayName(mParent->GetDisplayName()); SetPluginId(mParent->GetPluginId()); } } GMPContentParent::~GMPContentParent() { - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, - new DeleteTask<Transport>(GetTransport())); + RefPtr<DeleteTask<Transport>> task = new DeleteTask<Transport>(GetTransport()); + XRE_GetIOMessageLoop()->PostTask(task.forget()); } class ReleaseGMPContentParent : public Runnable { public: explicit ReleaseGMPContentParent(GMPContentParent* aToRelease) : mToRelease(aToRelease) {
--- a/dom/media/gmp/GMPDecryptorChild.cpp +++ b/dom/media/gmp/GMPDecryptorChild.cpp @@ -56,18 +56,18 @@ GMPDecryptorChild::CallOnGMPThread(Metho { if (ON_GMP_THREAD()) { // Use forwarding reference when we can. CallMethod(aMethod, Forward<ParamType>(aParams)...); } else { // Use const reference when we have to. auto m = &GMPDecryptorChild::CallMethod< decltype(aMethod), typename AddConstReference<ParamType>::Type...>; - auto t = NewRunnableMethod(this, m, aMethod, Forward<ParamType>(aParams)...); - mPlugin->GMPMessageLoop()->PostTask(FROM_HERE, t); + RefPtr<mozilla::Runnable> t = NewRunnableMethod(this, m, aMethod, Forward<ParamType>(aParams)...); + mPlugin->GMPMessageLoop()->PostTask(t.forget()); } } void GMPDecryptorChild::Init(GMPDecryptor* aSession) { MOZ_ASSERT(aSession); mSession = aSession; @@ -165,18 +165,18 @@ GMPDecryptorChild::KeyStatusChanged(cons } void GMPDecryptorChild::Decrypted(GMPBuffer* aBuffer, GMPErr aResult) { if (!ON_GMP_THREAD()) { // We should run this whole method on the GMP thread since the buffer needs // to be deleted after the SendDecrypted call. - auto t = NewRunnableMethod(this, &GMPDecryptorChild::Decrypted, aBuffer, aResult); - mPlugin->GMPMessageLoop()->PostTask(FROM_HERE, t); + RefPtr<Runnable> t = NewRunnableMethod(this, &GMPDecryptorChild::Decrypted, aBuffer, aResult); + mPlugin->GMPMessageLoop()->PostTask(t.forget()); return; } if (!aBuffer) { NS_WARNING("GMPDecryptorCallback passed bull GMPBuffer"); return; }
--- a/dom/media/gmp/GMPPlatform.cpp +++ b/dom/media/gmp/GMPPlatform.cpp @@ -68,17 +68,17 @@ public: void Post() { // We assert here for two reasons. // 1) Nobody should be blocking the main thread. // 2) This prevents deadlocks when doing sync calls to main which if the // main thread tries to do a sync call back to the calling thread. MOZ_ASSERT(!IsOnChildMainThread()); - mMessageLoop->PostTask(FROM_HERE, NewRunnableMethod(this, &SyncRunnable::Run)); + mMessageLoop->PostTask(NewRunnableMethod(this, &SyncRunnable::Run)); MonitorAutoLock lock(mMonitor); while (!mDone) { lock.Wait(); } } void Run() { @@ -116,17 +116,17 @@ CreateThread(GMPThread** aThread) GMPErr RunOnMainThread(GMPTask* aTask) { if (!aTask || !sMainLoop) { return GMPGenericErr; } RefPtr<Runnable> r = new Runnable(aTask); - sMainLoop->PostTask(FROM_HERE, NewRunnableMethod(r.get(), &Runnable::Run)); + sMainLoop->PostTask(NewRunnableMethod(r.get(), &Runnable::Run)); return GMPNoErr; } GMPErr SyncRunOnMainThread(GMPTask* aTask) { if (!aTask || !sMainLoop || IsOnChildMainThread()) { @@ -249,17 +249,17 @@ GMPThreadImpl::Post(GMPTask* aTask) if (!started) { NS_WARNING("Unable to start GMPThread!"); return; } } RefPtr<Runnable> r = new Runnable(aTask); - mThread.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(r.get(), &Runnable::Run)); + mThread.message_loop()->PostTask(NewRunnableMethod(r.get(), &Runnable::Run)); } void GMPThreadImpl::Join() { { MutexAutoLock lock(mMutex); if (mThread.IsRunning()) {
--- a/dom/media/gmp/GMPProcessParent.cpp +++ b/dom/media/gmp/GMPProcessParent.cpp @@ -80,17 +80,17 @@ GMPProcessParent::Launch(int32_t aTimeou return SyncLaunch(args, aTimeoutMs, base::GetCurrentProcessArchitecture()); } void GMPProcessParent::Delete(nsCOMPtr<nsIRunnable> aCallback) { mDeletedCallback = aCallback; - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, NewRunnableMethod(this, &GMPProcessParent::DoDelete)); + XRE_GetIOMessageLoop()->PostTask(NewRunnableMethod(this, &GMPProcessParent::DoDelete)); } void GMPProcessParent::DoDelete() { MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop()); Join();
--- a/dom/media/gmp/GMPServiceChild.cpp +++ b/dom/media/gmp/GMPServiceChild.cpp @@ -247,18 +247,18 @@ GeckoMediaPluginServiceChild::RemoveGMPC } GMPServiceChild::GMPServiceChild() { } GMPServiceChild::~GMPServiceChild() { - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, - new DeleteTask<Transport>(GetTransport())); + RefPtr<DeleteTask<Transport>> task = new DeleteTask<Transport>(GetTransport()); + XRE_GetIOMessageLoop()->PostTask(task.forget()); } PGMPContentParent* GMPServiceChild::AllocPGMPContentParent(Transport* aTransport, ProcessId aOtherPid) { MOZ_ASSERT(!mContentParents.GetWeak(aOtherPid));
--- a/dom/media/gmp/GMPServiceParent.cpp +++ b/dom/media/gmp/GMPServiceParent.cpp @@ -1776,18 +1776,18 @@ GeckoMediaPluginServiceParent::ClearStor if (NS_FAILED(DeleteDir(path))) { NS_WARNING("Failed to delete GMP storage directory"); } NS_DispatchToMainThread(new NotifyObserversTask("gmp-clear-storage-complete"), NS_DISPATCH_NORMAL); } GMPServiceParent::~GMPServiceParent() { - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, - new DeleteTask<Transport>(GetTransport())); + RefPtr<DeleteTask<Transport>> task = new DeleteTask<Transport>(GetTransport()); + XRE_GetIOMessageLoop()->PostTask(task.forget()); } bool GMPServiceParent::RecvLoadGMP(const nsCString& aNodeId, const nsCString& aAPI, nsTArray<nsCString>&& aTags, nsTArray<ProcessId>&& aAlreadyBridgedTo, ProcessId* aId,
--- a/dom/media/gmp/GMPStorageChild.cpp +++ b/dom/media/gmp/GMPStorageChild.cpp @@ -10,17 +10,17 @@ #define ON_GMP_THREAD() (mPlugin->GMPMessageLoop() == MessageLoop::current()) #define CALL_ON_GMP_THREAD(_func, ...) \ do { \ if (ON_GMP_THREAD()) { \ _func(__VA_ARGS__); \ } else { \ mPlugin->GMPMessageLoop()->PostTask( \ - FROM_HERE, NewRunnableMethod(this, &GMPStorageChild::_func, ##__VA_ARGS__) \ + NewRunnableMethod(this, &GMPStorageChild::_func, ##__VA_ARGS__) \ ); \ } \ } while(false) static nsTArray<uint8_t> ToArray(const uint8_t* aData, uint32_t aDataSize) { nsTArray<uint8_t> data;
--- a/dom/media/gmp/GMPVideoDecoderChild.cpp +++ b/dom/media/gmp/GMPVideoDecoderChild.cpp @@ -221,18 +221,17 @@ GMPVideoDecoderChild::Alloc(size_t aSize MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current()); bool rv; #ifndef SHMEM_ALLOC_IN_CHILD ++mNeedShmemIntrCount; rv = CallNeedShmem(aSize, aMem); --mNeedShmemIntrCount; if (mPendingDecodeComplete) { - auto t = NewRunnableMethod(this, &GMPVideoDecoderChild::RecvDecodingComplete); - mPlugin->GMPMessageLoop()->PostTask(FROM_HERE, t); + mPlugin->GMPMessageLoop()->PostTask(NewRunnableMethod(this, &GMPVideoDecoderChild::RecvDecodingComplete)); } #else #ifdef GMP_SAFE_SHMEM rv = AllocShmem(aSize, aType, aMem); #else rv = AllocUnsafeShmem(aSize, aType, aMem); #endif #endif
--- a/dom/media/gmp/GMPVideoEncoderChild.cpp +++ b/dom/media/gmp/GMPVideoEncoderChild.cpp @@ -202,18 +202,17 @@ GMPVideoEncoderChild::Alloc(size_t aSize MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current()); bool rv; #ifndef SHMEM_ALLOC_IN_CHILD ++mNeedShmemIntrCount; rv = CallNeedShmem(aSize, aMem); --mNeedShmemIntrCount; if (mPendingEncodeComplete) { - auto t = NewRunnableMethod(this, &GMPVideoEncoderChild::RecvEncodingComplete); - mPlugin->GMPMessageLoop()->PostTask(FROM_HERE, t); + mPlugin->GMPMessageLoop()->PostTask(NewRunnableMethod(this, &GMPVideoEncoderChild::RecvEncodingComplete)); } #else #ifdef GMP_SAFE_SHMEM rv = AllocShmem(aSize, aType, aMem); #else rv = AllocUnsafeShmem(aSize, aType, aMem); #endif #endif
--- a/dom/media/omx/MediaOmxReader.cpp +++ b/dom/media/omx/MediaOmxReader.cpp @@ -26,29 +26,30 @@ using namespace mozilla::gfx; using namespace mozilla::media; using namespace android; namespace mozilla { extern LazyLogModule gMediaDecoderLog; #define DECODER_LOG(type, msg) MOZ_LOG(gMediaDecoderLog, type, msg) -class MediaOmxReader::ProcessCachedDataTask : public Task +class MediaOmxReader::ProcessCachedDataTask : public Runnable { public: ProcessCachedDataTask(MediaOmxReader* aOmxReader, int64_t aOffset) : mOmxReader(aOmxReader), mOffset(aOffset) { } - void Run() + NS_IMETHOD Run() override { MOZ_ASSERT(!NS_IsMainThread()); MOZ_ASSERT(mOmxReader.get()); mOmxReader->ProcessCachedData(mOffset); + return NS_OK; } private: RefPtr<MediaOmxReader> mOmxReader; int64_t mOffset; }; // When loading an MP3 stream from a file, we need to parse the file's @@ -100,18 +101,18 @@ private: mLength -= length; mOffset += length; } if (static_cast<uint64_t>(mOffset) < mFullLength) { // We cannot read data in the main thread because it // might block for too long. Instead we post an IO task // to the IO thread if there is more data available. - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, - new ProcessCachedDataTask(mOmxReader.get(), mOffset)); + RefPtr<Runnable> task = new ProcessCachedDataTask(mOmxReader.get(), mOffset); + XRE_GetIOMessageLoop()->PostTask(task.forget()); } } RefPtr<MediaOmxReader> mOmxReader; uint64_t mLength; int64_t mOffset; uint64_t mFullLength; };
--- a/dom/media/systemservices/CamerasParent.cpp +++ b/dom/media/systemservices/CamerasParent.cpp @@ -160,35 +160,35 @@ CamerasParent::Observe(nsISupports *aSub nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); MOZ_ASSERT(obs); obs->RemoveObserver(this, NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID); StopVideoCapture(); return NS_OK; } nsresult -CamerasParent::DispatchToVideoCaptureThread(Runnable *event) +CamerasParent::DispatchToVideoCaptureThread(Runnable* event) { // Don't try to dispatch if we're already on the right thread. // There's a potential deadlock because the mThreadMonitor is likely // to be taken already. MOZ_ASSERT(!mVideoCaptureThread || mVideoCaptureThread->thread_id() != PlatformThread::CurrentId()); MonitorAutoLock lock(mThreadMonitor); while(mChildIsAlive && mWebRTCAlive && (!mVideoCaptureThread || !mVideoCaptureThread->IsRunning())) { mThreadMonitor.Wait(); } if (!mVideoCaptureThread || !mVideoCaptureThread->IsRunning()) { return NS_ERROR_FAILURE; } - mVideoCaptureThread->message_loop()->PostTask(FROM_HERE, - new RunnableTask(event)); + RefPtr<Runnable> addrefedEvent = event; + mVideoCaptureThread->message_loop()->PostTask(addrefedEvent.forget()); return NS_OK; } void CamerasParent::StopVideoCapture() { LOG((__PRETTY_FUNCTION__)); // We are called from the main thread (xpcom-shutdown) or
--- a/dom/media/systemservices/CamerasParent.h +++ b/dom/media/systemservices/CamerasParent.h @@ -124,17 +124,18 @@ protected: void StopCapture(const int& aCapEngine, const int& capnum); int ReleaseCaptureDevice(const int& aCapEngine, const int& capnum); bool SetupEngine(CaptureEngine aCapEngine); bool EnsureInitialized(int aEngine); void CloseEngines(); void StopIPC(); void StopVideoCapture(); - nsresult DispatchToVideoCaptureThread(Runnable *event); + // Can't take already_AddRefed because it can fail in stupid ways. + nsresult DispatchToVideoCaptureThread(Runnable* event); EngineHelper mEngines[CaptureEngine::MaxEngine]; nsTArray<CallbackHelper*> mCallbacks; // image buffers mozilla::ShmemPool mShmemPool; // PBackground parent thread
--- a/dom/media/systemservices/CamerasUtils.h +++ b/dom/media/systemservices/CamerasUtils.h @@ -34,27 +34,12 @@ public: return NS_OK; } private: ~ThreadDestructor() {} nsCOMPtr<nsIThread> mThread; }; -class RunnableTask : public Task -{ -public: - explicit RunnableTask(Runnable* aRunnable) - : mRunnable(aRunnable) {} - - void Run() override { - mRunnable->Run(); - } - -private: - ~RunnableTask() {} - RefPtr<Runnable> mRunnable; -}; - } } #endif // mozilla_CameraUtils_h
--- a/dom/media/systemservices/MediaSystemResourceManager.cpp +++ b/dom/media/systemservices/MediaSystemResourceManager.cpp @@ -34,30 +34,16 @@ MediaSystemResourceManager::Shutdown() { MOZ_ASSERT(InImageBridgeChildThread()); if (sSingleton) { sSingleton->CloseIPC(); sSingleton = nullptr; } } -class RunnableCallTask : public Task -{ -public: - explicit RunnableCallTask(nsIRunnable* aRunnable) - : mRunnable(aRunnable) {} - - void Run() override - { - mRunnable->Run(); - } -protected: - nsCOMPtr<nsIRunnable> mRunnable; -}; - /* static */ void MediaSystemResourceManager::Init() { if (!ImageBridgeChild::IsCreated()) { NS_WARNING("ImageBridge does not exist"); return; } @@ -72,28 +58,27 @@ MediaSystemResourceManager::Init() } return; } ReentrantMonitor barrier("MediaSystemResourceManager::Init"); ReentrantMonitorAutoEnter autoMon(barrier); bool done = false; - nsCOMPtr<nsIRunnable> runnable = + RefPtr<Runnable> runnable = NS_NewRunnableFunction([&]() { if (!sSingleton) { sSingleton = new MediaSystemResourceManager(); } ReentrantMonitorAutoEnter autoMon(barrier); done = true; barrier.NotifyAll(); }); - ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask( - FROM_HERE, new RunnableCallTask(runnable)); + ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(runnable.forget()); // should stop the thread until done. while (!done) { barrier.Wait(); } } @@ -209,17 +194,16 @@ MediaSystemResourceManager::Acquire(Medi } // State Check if (aClient->mResourceState != MediaSystemResourceClient::RESOURCE_STATE_START) { HandleAcquireResult(aClient->mId, false); return; } aClient->mResourceState = MediaSystemResourceClient::RESOURCE_STATE_WAITING; ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask( - FROM_HERE, NewRunnableMethod( this, &MediaSystemResourceManager::DoAcquire, aClient->mId)); } bool MediaSystemResourceManager::AcquireSyncNoWait(MediaSystemResourceClient* aClient) @@ -253,17 +237,16 @@ MediaSystemResourceManager::AcquireSyncN } // Hold barrier Monitor until acquire task end. aClient->mAcquireSyncWaitMonitor = &barrier; aClient->mAcquireSyncWaitDone = &done; aClient->mResourceState = MediaSystemResourceClient::RESOURCE_STATE_WAITING; } ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask( - FROM_HERE, NewRunnableMethod( this, &MediaSystemResourceManager::DoAcquire, aClient->mId)); // should stop the thread until done. while (!done) { barrier.Wait(); @@ -321,17 +304,16 @@ MediaSystemResourceManager::ReleaseResou aClient->mResourceState = MediaSystemResourceClient::RESOURCE_STATE_END; return; } aClient->mResourceState = MediaSystemResourceClient::RESOURCE_STATE_END; ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask( - FROM_HERE, NewRunnableMethod( this, &MediaSystemResourceManager::DoRelease, aClient->mId)); } } void @@ -350,17 +332,16 @@ MediaSystemResourceManager::RecvResponse HandleAcquireResult(aId, aSuccess); } void MediaSystemResourceManager::HandleAcquireResult(uint32_t aId, bool aSuccess) { if (!InImageBridgeChildThread()) { ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask( - FROM_HERE, NewRunnableMethod( this, &MediaSystemResourceManager::HandleAcquireResult, aId, aSuccess)); return; }
--- a/dom/media/systemservices/MediaUtils.h +++ b/dom/media/systemservices/MediaUtils.h @@ -195,41 +195,46 @@ private: Run() { return mOnRun(); } OnRunType mOnRun; }; template<typename OnRunType> -LambdaRunnable<OnRunType>* +already_AddRefed<LambdaRunnable<OnRunType>> NewRunnableFrom(OnRunType&& aOnRun) { - return new LambdaRunnable<OnRunType>(Forward<OnRunType>(aOnRun)); + typedef LambdaRunnable<OnRunType> LambdaType; + RefPtr<LambdaType> lambda = new LambdaType(Forward<OnRunType>(aOnRun)); + return lambda.forget(); } template<typename OnRunType> -class LambdaTask : public Task +class LambdaTask : public Runnable { public: explicit LambdaTask(OnRunType&& aOnRun) : mOnRun(Move(aOnRun)) {} private: - void - Run() + NS_IMETHOD + Run() override { - return mOnRun(); + mOnRun(); + return NS_OK; } OnRunType mOnRun; }; template<typename OnRunType> -LambdaTask<OnRunType>* +already_AddRefed<LambdaTask<OnRunType>> NewTaskFrom(OnRunType&& aOnRun) { - return new LambdaTask<OnRunType>(Forward<OnRunType>(aOnRun)); + typedef LambdaTask<OnRunType> LambdaType; + RefPtr<LambdaType> lambda = new LambdaType(Forward<OnRunType>(aOnRun)); + return lambda.forget(); } /* media::CoatCheck - There and back again. Park an object in exchange for an id. * * A common problem with calling asynchronous functions that do work on other * threads or processes is how to pass in a heap object for use once the * function completes, without requiring that object to have threadsafe * refcounting, contain mutexes, be marshaled, or leak if things fail
--- a/dom/media/webaudio/blink/ReverbConvolver.cpp +++ b/dom/media/webaudio/blink/ReverbConvolver.cpp @@ -153,18 +153,18 @@ ReverbConvolver::ReverbConvolver(const f // Start up background thread // FIXME: would be better to up the thread priority here. It doesn't need to be real-time, but higher than the default... if (this->useBackgroundThreads() && m_backgroundStages.Length() > 0) { if (!m_backgroundThread.Start()) { NS_WARNING("Cannot start convolver thread."); return; } - CancelableTask* task = NewRunnableMethod(this, &ReverbConvolver::backgroundThreadEntry); - m_backgroundThread.message_loop()->PostTask(FROM_HERE, task); + m_backgroundThread.message_loop()->PostTask( + NewRunnableMethod(this, &ReverbConvolver::backgroundThreadEntry)); } } ReverbConvolver::~ReverbConvolver() { // Wait for background thread to stop if (useBackgroundThreads() && m_backgroundThread.IsRunning()) { m_wantsToExit = true;
--- a/dom/plugins/ipc/BrowserStreamChild.cpp +++ b/dom/plugins/ipc/BrowserStreamChild.cpp @@ -185,17 +185,17 @@ BrowserStreamChild::NPN_DestroyStream(NP SendNPN_DestroyStream(reason); EnsureDeliveryPending(); } void BrowserStreamChild::EnsureDeliveryPending() { - MessageLoop::current()->PostTask(FROM_HERE, + MessageLoop::current()->PostTask( mDeliveryTracker.NewRunnableMethod(&BrowserStreamChild::Deliver)); } void BrowserStreamChild::Deliver() { while (kStreamOpen == mStreamStatus && mPendingData.Length()) { if (DeliverPendingData() && kStreamOpen == mStreamStatus) {
--- a/dom/plugins/ipc/ChildAsyncCall.cpp +++ b/dom/plugins/ipc/ChildAsyncCall.cpp @@ -14,36 +14,39 @@ namespace plugins { ChildAsyncCall::ChildAsyncCall(PluginInstanceChild* instance, PluginThreadCallback aFunc, void* aUserData) : mInstance(instance) , mFunc(aFunc) , mData(aUserData) { } -void +nsresult ChildAsyncCall::Cancel() { mInstance = nullptr; mFunc = nullptr; mData = nullptr; + return NS_OK; } void ChildAsyncCall::RemoveFromAsyncList() { if (mInstance) { MutexAutoLock lock(mInstance->mAsyncCallMutex); mInstance->mPendingAsyncCalls.RemoveElement(this); } } -void +NS_IMETHODIMP ChildAsyncCall::Run() { RemoveFromAsyncList(); if (mFunc) mFunc(mData); + + return NS_OK; } } // namespace plugins } // namespace mozilla
--- a/dom/plugins/ipc/ChildAsyncCall.h +++ b/dom/plugins/ipc/ChildAsyncCall.h @@ -4,33 +4,33 @@ /* 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/. */ #ifndef mozilla_plugins_ChildAsyncCall_h #define mozilla_plugins_ChildAsyncCall_h #include "PluginMessageUtils.h" -#include "base/task.h" +#include "nsThreadUtils.h" namespace mozilla { namespace plugins { typedef void (*PluginThreadCallback)(void*); class PluginInstanceChild; -class ChildAsyncCall : public CancelableTask +class ChildAsyncCall : public CancelableRunnable { public: ChildAsyncCall(PluginInstanceChild* instance, PluginThreadCallback aFunc, void* aUserData); - void Run() override; - void Cancel() override; + NS_IMETHOD Run() override; + nsresult Cancel() override; protected: PluginInstanceChild* mInstance; PluginThreadCallback mFunc; void* mData; void RemoveFromAsyncList(); };
--- a/dom/plugins/ipc/PluginInstanceChild.cpp +++ b/dom/plugins/ipc/PluginInstanceChild.cpp @@ -190,18 +190,16 @@ PluginInstanceChild::PluginInstanceChild , mLayersRendering(false) #ifdef XP_WIN , mCurrentSurfaceActor(nullptr) , mBackSurfaceActor(nullptr) #endif , mAccumulatedInvalidRect(0,0,0,0) , mIsTransparent(false) , mSurfaceType(gfxSurfaceType::Max) - , mCurrentInvalidateTask(nullptr) - , mCurrentAsyncSetWindowTask(nullptr) , mPendingPluginCall(false) , mDoAlphaExtraction(false) , mHasPainted(false) , mSurfaceDifferenceRect(0,0,0,0) , mDestroyed(false) #ifdef XP_WIN , mLastKeyEventConsumed(false) #endif // #ifdef XP_WIN @@ -2619,48 +2617,50 @@ PluginInstanceChild::FlashThrottleAsyncM { if (mInstance) { return mWindowed ? mInstance->mPluginWndProc : mInstance->mWinlessThrottleOldWndProc; } return nullptr; } -void +NS_IMETHODIMP PluginInstanceChild::FlashThrottleAsyncMsg::Run() { RemoveFromAsyncList(); // GetProc() checks mInstance, and pulls the procedure from // PluginInstanceChild. We don't transport sub-class procedure // ptrs around in FlashThrottleAsyncMsg msgs. if (!GetProc()) - return; + return NS_OK; // deliver the event to flash CallWindowProc(GetProc(), GetWnd(), GetMsg(), GetWParam(), GetLParam()); + return NS_OK; } void PluginInstanceChild::FlashThrottleMessage(HWND aWnd, UINT aMsg, WPARAM aWParam, LPARAM aLParam, bool isWindowed) { // We reuse ChildAsyncCall so we get the cancelation work // that's done in Destroy. - FlashThrottleAsyncMsg* task = new FlashThrottleAsyncMsg(this, - aWnd, aMsg, aWParam, aLParam, isWindowed); + RefPtr<FlashThrottleAsyncMsg> task = + new FlashThrottleAsyncMsg(this, aWnd, aMsg, aWParam, + aLParam, isWindowed); { MutexAutoLock lock(mAsyncCallMutex); mPendingAsyncCalls.AppendElement(task); } - MessageLoop::current()->PostDelayedTask(FROM_HERE, - task, kFlashWMUSERMessageThrottleDelayMs); + MessageLoop::current()->PostDelayedTask(task.forget(), + kFlashWMUSERMessageThrottleDelayMs); } #endif // OS_WIN bool PluginInstanceChild::AnswerSetPluginFocus() { MOZ_LOG(GetPluginLog(), LogLevel::Debug, ("%s", FULLFUNCTION)); @@ -2792,44 +2792,45 @@ public: const bool aSeekable) : ChildAsyncCall(aInstance, nullptr, nullptr) , mBrowserStreamChild(aBrowserStreamChild) , mMimeType(aMimeType) , mSeekable(aSeekable) { } - void Run() override + NS_IMETHOD Run() override { RemoveFromAsyncList(); uint16_t stype = NP_NORMAL; NPError rv = mInstance->DoNPP_NewStream(mBrowserStreamChild, mMimeType, mSeekable, &stype); DebugOnly<bool> sendOk = mBrowserStreamChild->SendAsyncNPP_NewStreamResult(rv, stype); MOZ_ASSERT(sendOk); + return NS_OK; } private: BrowserStreamChild* mBrowserStreamChild; const nsCString mMimeType; const bool mSeekable; }; bool PluginInstanceChild::RecvAsyncNPP_NewStream(PBrowserStreamChild* actor, const nsCString& mimeType, const bool& seekable) { // Reusing ChildAsyncCall so that the task is cancelled properly on Destroy BrowserStreamChild* child = static_cast<BrowserStreamChild*>(actor); - NewStreamAsyncCall* task = new NewStreamAsyncCall(this, child, mimeType, - seekable); - PostChildAsyncCall(task); + RefPtr<NewStreamAsyncCall> task = + new NewStreamAsyncCall(this, child, mimeType, seekable); + PostChildAsyncCall(task.forget()); return true; } PBrowserStreamChild* PluginInstanceChild::AllocPBrowserStreamChild(const nsCString& url, const uint32_t& length, const uint32_t& lastmodified, PStreamNotifyChild* notifyData, @@ -3298,17 +3299,18 @@ PluginInstanceChild::RecvAsyncSetWindow( // RPC call, and both Flash and Java don't expect to receive setwindow calls // at arbitrary times. mCurrentAsyncSetWindowTask = NewRunnableMethod<PluginInstanceChild, void (PluginInstanceChild::*)(const gfxSurfaceType&, const NPRemoteWindow&, bool), const gfxSurfaceType&, const NPRemoteWindow&, bool> (this, &PluginInstanceChild::DoAsyncSetWindow, aSurfaceType, aWindow, true); - MessageLoop::current()->PostTask(FROM_HERE, mCurrentAsyncSetWindowTask); + RefPtr<Runnable> addrefedTask = mCurrentAsyncSetWindowTask; + MessageLoop::current()->PostTask(addrefedTask.forget()); return true; } void PluginInstanceChild::DoAsyncSetWindow(const gfxSurfaceType& aSurfaceType, const NPRemoteWindow& aWindow, bool aIsAsync) @@ -4217,17 +4219,18 @@ PluginInstanceChild::AsyncShowPluginFram // paints via paint events - it will drive painting via its own events // and/or DidComposite callbacks. if (IsUsingDirectDrawing()) { return; } mCurrentInvalidateTask = NewRunnableMethod(this, &PluginInstanceChild::InvalidateRectDelayed); - MessageLoop::current()->PostTask(FROM_HERE, mCurrentInvalidateTask); + RefPtr<Runnable> addrefedTask = mCurrentInvalidateTask; + MessageLoop::current()->PostTask(addrefedTask.forget()); } void PluginInstanceChild::InvalidateRect(NPRect* aInvalidRect) { NS_ASSERTION(aInvalidRect, "Null pointer!"); #ifdef OS_WIN @@ -4373,28 +4376,30 @@ PluginInstanceChild::UnscheduleTimer(uin return; mTimers.RemoveElement(id, ChildTimer::IDComparator()); } void PluginInstanceChild::AsyncCall(PluginThreadCallback aFunc, void* aUserData) { - ChildAsyncCall* task = new ChildAsyncCall(this, aFunc, aUserData); - PostChildAsyncCall(task); + RefPtr<ChildAsyncCall> task = new ChildAsyncCall(this, aFunc, aUserData); + PostChildAsyncCall(task.forget()); } void -PluginInstanceChild::PostChildAsyncCall(ChildAsyncCall* aTask) +PluginInstanceChild::PostChildAsyncCall(already_AddRefed<ChildAsyncCall> aTask) { + RefPtr<ChildAsyncCall> task = aTask; + { MutexAutoLock lock(mAsyncCallMutex); - mPendingAsyncCalls.AppendElement(aTask); - } - ProcessChild::message_loop()->PostTask(FROM_HERE, aTask); + mPendingAsyncCalls.AppendElement(task); + } + ProcessChild::message_loop()->PostTask(task.forget()); } void PluginInstanceChild::SwapSurfaces() { RefPtr<gfxASurface> tmpsurf = mCurrentSurface; #ifdef XP_WIN PPluginSurfaceChild* tmpactor = mCurrentSurfaceActor;
--- a/dom/plugins/ipc/PluginInstanceChild.h +++ b/dom/plugins/ipc/PluginInstanceChild.h @@ -254,17 +254,17 @@ public: void Invalidate(); #endif // definied(MOZ_WIDGET_COCOA) uint32_t ScheduleTimer(uint32_t interval, bool repeat, TimerFunc func); void UnscheduleTimer(uint32_t id); void AsyncCall(PluginThreadCallback aFunc, void* aUserData); // This function is a more general version of AsyncCall - void PostChildAsyncCall(ChildAsyncCall* aTask); + void PostChildAsyncCall(already_AddRefed<ChildAsyncCall> aTask); int GetQuirks(); void NPN_URLRedirectResponse(void* notifyData, NPBool allow); NPError NPN_InitAsyncSurface(NPSize *size, NPImageFormat format, void *initData, NPAsyncSurface *surface); @@ -379,17 +379,17 @@ private: : ChildAsyncCall(aInst, nullptr, nullptr), mWnd(aWnd), mMsg(aMsg), mWParam(aWParam), mLParam(aLParam), mWindowed(isWindowed) {} - void Run() override; + NS_IMETHOD Run() override; WNDPROC GetProc(); HWND GetWnd() { return mWnd; } UINT GetMsg() { return mMsg; } WPARAM GetWParam() { return mWParam; } LPARAM GetLParam() { return mLParam; } private: @@ -441,17 +441,17 @@ private: }; nsRefPtrHashtable<nsPtrHashKey<NPAsyncSurface>, DirectBitmap> mDirectBitmaps; #if defined(XP_WIN) nsDataHashtable<nsPtrHashKey<NPAsyncSurface>, WindowsHandle> mDxgiSurfaces; #endif mozilla::Mutex mAsyncInvalidateMutex; - CancelableTask *mAsyncInvalidateTask; + CancelableRunnable *mAsyncInvalidateTask; // Cached scriptable actors to avoid IPC churn PluginScriptableObjectChild* mCachedWindowActor; PluginScriptableObjectChild* mCachedElementActor; #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX) NPSetWindowCallbackStruct mWsInfo; #ifdef MOZ_WIDGET_GTK @@ -632,20 +632,20 @@ private: // and does not remember their transparent state // and p->getvalue return always false bool mIsTransparent; // Surface type optimized of parent process gfxSurfaceType mSurfaceType; // Keep InvalidateRect task pointer to be able Cancel it on Destroy - CancelableTask *mCurrentInvalidateTask; + RefPtr<CancelableRunnable> mCurrentInvalidateTask; // Keep AsyncSetWindow task pointer to be able to Cancel it on Destroy - CancelableTask *mCurrentAsyncSetWindowTask; + RefPtr<CancelableRunnable> mCurrentAsyncSetWindowTask; // True while plugin-child in plugin call // Use to prevent plugin paint re-enter bool mPendingPluginCall; // On some platforms, plugins may not support rendering to a surface with // alpha, or not support rendering to an image surface. // In those cases we need to draw to a temporary platform surface; we cache
--- a/dom/plugins/ipc/PluginInstanceParent.cpp +++ b/dom/plugins/ipc/PluginInstanceParent.cpp @@ -146,17 +146,16 @@ PluginInstanceParent::PluginInstancePare , mNestedEventState(false) #endif // defined(XP_WIN) #if defined(XP_MACOSX) , mShWidth(0) , mShHeight(0) , mShColorSpace(nullptr) #endif #if defined(XP_WIN) - , mCaptureRefreshTask(nullptr) , mValidFirstCapture(false) , mIsScrolling(false) #endif { #if defined(OS_WIN) if (!sPluginInstanceList) { sPluginInstanceList = new nsClassHashtable<nsVoidPtrHashKey, PluginInstanceParent>(); } @@ -1220,17 +1219,18 @@ void PluginInstanceParent::ScheduleScrollCapture(int aTimeout) { if (mCaptureRefreshTask) { return; } CAPTURE_LOG("delayed scroll capture requested."); mCaptureRefreshTask = NewRunnableMethod(this, &PluginInstanceParent::ScheduledUpdateScrollCaptureCallback); - MessageLoop::current()->PostDelayedTask(FROM_HERE, mCaptureRefreshTask, + RefPtr<Runnable> addrefedTask = mCaptureRefreshTask; + MessageLoop::current()->PostDelayedTask(addrefedTask.forget(), kScrollCaptureDelayMs); } void PluginInstanceParent::ScheduledUpdateScrollCaptureCallback() { CAPTURE_LOG("taking delayed scrollcapture."); mCaptureRefreshTask = nullptr;
--- a/dom/plugins/ipc/PluginInstanceParent.h +++ b/dom/plugins/ipc/PluginInstanceParent.h @@ -469,17 +469,17 @@ private: #if defined(XP_WIN) void ScheduleScrollCapture(int aTimeout); void ScheduledUpdateScrollCaptureCallback(); bool UpdateScrollCapture(bool& aRequestNewCapture); void CancelScheduledScrollCapture(); RefPtr<gfxASurface> mScrollCapture; - CancelableTask* mCaptureRefreshTask; + RefPtr<CancelableRunnable> mCaptureRefreshTask; bool mValidFirstCapture; bool mIsScrolling; #endif }; } // namespace plugins } // namespace mozilla
--- a/dom/plugins/ipc/PluginModuleChild.cpp +++ b/dom/plugins/ipc/PluginModuleChild.cpp @@ -161,17 +161,18 @@ PluginModuleChild::PluginModuleChild(boo PluginModuleChild::~PluginModuleChild() { if (mTransport) { // For some reason IPDL doesn't automatically delete the channel for a // bridged protocol (bug 1090570). So we have to do it ourselves. This // code is only invoked for PluginModuleChild instances created via // bridging; otherwise mTransport is null. - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new DeleteTask<Transport>(mTransport)); + RefPtr<DeleteTask<Transport>> task = new DeleteTask<Transport>(mTransport); + XRE_GetIOMessageLoop()->PostTask(task.forget()); } if (mIsChrome) { MOZ_ASSERT(gChromeInstance == this); // We don't unload the plugin library in case it uses atexit handlers or // other similar hooks. @@ -826,17 +827,19 @@ PluginModuleChild::ActorDestroy(ActorDes { if (!mIsChrome) { PluginModuleChild* chromeInstance = PluginModuleChild::GetChrome(); if (chromeInstance) { chromeInstance->SendNotifyContentModuleDestroyed(); } // Destroy ourselves once we finish other teardown activities. - MessageLoop::current()->PostTask(FROM_HERE, new DeleteTask<PluginModuleChild>(this)); + RefPtr<DeleteTask<PluginModuleChild>> task = + new DeleteTask<PluginModuleChild>(this); + MessageLoop::current()->PostTask(task.forget()); return; } if (AbnormalShutdown == why) { NS_WARNING("shutting down early because of crash!"); ProcessChild::QuickExit(); } @@ -2201,36 +2204,38 @@ class AsyncNewResultSender : public Chil { public: AsyncNewResultSender(PluginInstanceChild* aInstance, NPError aResult) : ChildAsyncCall(aInstance, nullptr, nullptr) , mResult(aResult) { } - void Run() override + NS_IMETHOD Run() override { RemoveFromAsyncList(); DebugOnly<bool> sendOk = mInstance->SendAsyncNPP_NewResult(mResult); MOZ_ASSERT(sendOk); + return NS_OK; } private: NPError mResult; }; static void RunAsyncNPP_New(void* aChildInstance) { MOZ_ASSERT(aChildInstance); PluginInstanceChild* childInstance = static_cast<PluginInstanceChild*>(aChildInstance); NPError rv = childInstance->DoNPP_New(); - AsyncNewResultSender* task = new AsyncNewResultSender(childInstance, rv); - childInstance->PostChildAsyncCall(task); + RefPtr<AsyncNewResultSender> task = + new AsyncNewResultSender(childInstance, rv); + childInstance->PostChildAsyncCall(task.forget()); } bool PluginModuleChild::RecvAsyncNPP_New(PPluginInstanceChild* aActor) { PLUGIN_LOG_DEBUG_METHOD; PluginInstanceChild* childInstance = reinterpret_cast<PluginInstanceChild*>(aActor);
--- a/dom/plugins/ipc/PluginModuleParent.cpp +++ b/dom/plugins/ipc/PluginModuleParent.cpp @@ -145,17 +145,17 @@ mozilla::plugins::SetupBridge(uint32_t a return true; } #ifdef MOZ_CRASHREPORTER_INJECTOR /** * Use for executing CreateToolhelp32Snapshot off main thread */ -class mozilla::plugins::FinishInjectorInitTask : public CancelableTask +class mozilla::plugins::FinishInjectorInitTask : public mozilla::CancelableRunnable { public: FinishInjectorInitTask() : mMutex("FlashInjectorInitTask::mMutex") , mParent(nullptr) , mMainThreadMsgLoop(MessageLoop::current()) { MOZ_ASSERT(NS_IsMainThread()); @@ -164,44 +164,41 @@ public: void Init(PluginModuleChromeParent* aParent) { MOZ_ASSERT(aParent); mParent = aParent; } void PostToMainThread() { + RefPtr<Runnable> self = this; mSnapshot.own(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)); - bool deleteThis = false; { // Scope for lock mozilla::MutexAutoLock lock(mMutex); if (mMainThreadMsgLoop) { - mMainThreadMsgLoop->PostTask(FROM_HERE, this); - } else { - deleteThis = true; + mMainThreadMsgLoop->PostTask(self.forget()); } } - if (deleteThis) { - delete this; - } } - void Run() override + NS_IMETHOD Run() override { mParent->DoInjection(mSnapshot); // We don't need to hold this lock during DoInjection, but we do need // to obtain it before returning from Run() to ensure that // PostToMainThread has completed before we return. mozilla::MutexAutoLock lock(mMutex); + return NS_OK; } - void Cancel() override + nsresult Cancel() override { mozilla::MutexAutoLock lock(mMutex); mMainThreadMsgLoop = nullptr; + return NS_OK; } private: mozilla::Mutex mMutex; nsAutoHandle mSnapshot; PluginModuleChromeParent* mParent; MessageLoop* mMainThreadMsgLoop; }; @@ -705,18 +702,19 @@ PluginModuleParent::~PluginModuleParent( PluginModuleContentParent::PluginModuleContentParent(bool aAllowAsyncInit) : PluginModuleParent(false, aAllowAsyncInit) { Preferences::RegisterCallback(TimeoutChanged, kContentTimeoutPref, this); } PluginModuleContentParent::~PluginModuleContentParent() { - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, - new DeleteTask<Transport>(GetTransport())); + RefPtr<DeleteTask<Transport>> task = new DeleteTask<Transport>(GetTransport()); + XRE_GetIOMessageLoop()->PostTask(task.forget()); + Preferences::UnregisterCallback(TimeoutChanged, kContentTimeoutPref, this); } bool PluginModuleChromeParent::sInstantiated = false; PluginModuleChromeParent::PluginModuleChromeParent(const char* aFilePath, uint32_t aPluginId, @@ -901,17 +899,16 @@ PluginModuleChromeParent::CleanupFromTim { if (mShutdown) { return; } if (!OkToCleanup()) { // there's still plugin code on the C++ stack, try again MessageLoop::current()->PostDelayedTask( - FROM_HERE, mChromeTaskFactory.NewRunnableMethod( &PluginModuleChromeParent::CleanupFromTimeout, aFromHangUI), 10); return; } /* If the plugin container was terminated by the Plugin Hang UI, then either the I/O thread detects a channel error, or the main thread must set the error (whomever gets there first). @@ -1166,17 +1163,16 @@ CreatePluginMinidump(base::ProcessId pro } #endif bool PluginModuleChromeParent::ShouldContinueFromReplyTimeout() { if (mIsFlashPlugin) { MessageLoop::current()->PostTask( - FROM_HERE, mTaskFactory.NewRunnableMethod( &PluginModuleChromeParent::NotifyFlashHang)); } #ifdef XP_WIN if (LaunchHangUI()) { return true; } @@ -1344,17 +1340,16 @@ PluginModuleChromeParent::TerminateChild mPluginCpuUsageOnHang.Clear(); } #endif // this must run before the error notification from the channel, // or not at all bool isFromHangUI = aMsgLoop != MessageLoop::current(); aMsgLoop->PostTask( - FROM_HERE, mChromeTaskFactory.NewRunnableMethod( &PluginModuleChromeParent::CleanupFromTimeout, isFromHangUI)); if (!childOpened || !KillProcess(geckoChildProcess, 1, false)) { NS_WARNING("failed to kill subprocess!"); } } @@ -1594,17 +1589,16 @@ PluginModuleParent::ActorDestroy(ActorDe { switch (why) { case AbnormalShutdown: { mShutdown = true; // Defer the PluginCrashed method so that we don't re-enter // and potentially modify the actor child list while enumerating it. if (mPlugin) MessageLoop::current()->PostTask( - FROM_HERE, mTaskFactory.NewRunnableMethod( &PluginModuleParent::NotifyPluginCrashed)); break; } case NormalShutdown: mShutdown = true; break; @@ -1650,17 +1644,16 @@ PluginModuleParent::NotifyFlashHang() } void PluginModuleParent::NotifyPluginCrashed() { if (!OkToCleanup()) { // there's still plugin code on the C++ stack. try again MessageLoop::current()->PostDelayedTask( - FROM_HERE, mTaskFactory.NewRunnableMethod( &PluginModuleParent::NotifyPluginCrashed), 10); return; } if (mPlugin) mPlugin->PluginCrashed(mPluginDumpID, mBrowserDumpID); } @@ -3151,17 +3144,16 @@ PluginModuleChromeParent::InitializeInje NS_LITERAL_CSTRING(FLASH_PLUGIN_PREFIX))) return; TimeStamp th32Start = TimeStamp::Now(); mFinishInitTask = mChromeTaskFactory.NewTask<FinishInjectorInitTask>(); mFinishInitTask->Init(this); if (!::QueueUserWorkItem(&PluginModuleChromeParent::GetToolhelpSnapshot, mFinishInitTask, WT_EXECUTEDEFAULT)) { - delete mFinishInitTask; mFinishInitTask = nullptr; return; } TimeStamp th32End = TimeStamp::Now(); mTimeBlocked += (th32End - th32Start); } void
--- a/dom/plugins/ipc/PluginModuleParent.h +++ b/dom/plugins/ipc/PluginModuleParent.h @@ -603,33 +603,34 @@ private: void InitializeInjector(); void DoInjection(const nsAutoHandle& aSnapshot); static DWORD WINAPI GetToolhelpSnapshot(LPVOID aContext); void OnCrash(DWORD processID) override; DWORD mFlashProcess1; DWORD mFlashProcess2; - mozilla::plugins::FinishInjectorInitTask* mFinishInitTask; + RefPtr<mozilla::plugins::FinishInjectorInitTask> mFinishInitTask; #endif void OnProcessLaunched(const bool aSucceeded); class LaunchedTask : public LaunchCompleteTask { public: explicit LaunchedTask(PluginModuleChromeParent* aModule) : mModule(aModule) { MOZ_ASSERT(aModule); } - void Run() override + NS_IMETHOD Run() override { mModule->OnProcessLaunched(mLaunchSucceeded); + return NS_OK; } private: PluginModuleChromeParent* mModule; }; friend class LaunchedTask;
--- a/dom/plugins/ipc/PluginProcessParent.cpp +++ b/dom/plugins/ipc/PluginProcessParent.cpp @@ -197,18 +197,17 @@ PluginProcessParent::Delete() MessageLoop* currentLoop = MessageLoop::current(); MessageLoop* ioLoop = XRE_GetIOMessageLoop(); if (currentLoop == ioLoop) { delete this; return; } - ioLoop->PostTask(FROM_HERE, - NewRunnableMethod(this, &PluginProcessParent::Delete)); + ioLoop->PostTask(NewRunnableMethod(this, &PluginProcessParent::Delete)); } void PluginProcessParent::SetCallRunnableImmediately(bool aCallImmediately) { mRunCompleteTaskImmediately = aCallImmediately; } @@ -242,27 +241,27 @@ PluginProcessParent::WaitUntilConnected( } void PluginProcessParent::OnChannelConnected(int32_t peer_pid) { GeckoChildProcessHost::OnChannelConnected(peer_pid); if (mLaunchCompleteTask && !mRunCompleteTaskImmediately) { mLaunchCompleteTask->SetLaunchSucceeded(); - mMainMsgLoop->PostTask(FROM_HERE, mTaskFactory.NewRunnableMethod( + mMainMsgLoop->PostTask(mTaskFactory.NewRunnableMethod( &PluginProcessParent::RunLaunchCompleteTask)); } } void PluginProcessParent::OnChannelError() { GeckoChildProcessHost::OnChannelError(); if (mLaunchCompleteTask && !mRunCompleteTaskImmediately) { - mMainMsgLoop->PostTask(FROM_HERE, mTaskFactory.NewRunnableMethod( + mMainMsgLoop->PostTask(mTaskFactory.NewRunnableMethod( &PluginProcessParent::RunLaunchCompleteTask)); } } bool PluginProcessParent::IsConnected() { mozilla::MonitorAutoLock lock(mMonitor);
--- a/dom/plugins/ipc/PluginProcessParent.h +++ b/dom/plugins/ipc/PluginProcessParent.h @@ -20,17 +20,17 @@ #include "mozilla/plugins/TaskFactory.h" #include "mozilla/UniquePtr.h" #include "nsCOMPtr.h" #include "nsIRunnable.h" namespace mozilla { namespace plugins { -class LaunchCompleteTask : public Task +class LaunchCompleteTask : public Runnable { public: LaunchCompleteTask() : mLaunchSucceeded(false) { } void SetLaunchSucceeded() { mLaunchSucceeded = true; }
--- a/dom/plugins/ipc/TaskFactory.h +++ b/dom/plugins/ipc/TaskFactory.h @@ -31,67 +31,72 @@ private: public: template<typename... Args> explicit TaskWrapper(RevocableStore* store, Args&&... args) : TaskType(mozilla::Forward<Args>(args)...) , revocable_(store) { } - virtual void Run() { + NS_IMETHOD Run() override { if (!revocable_.revoked()) TaskType::Run(); + return NS_OK; } private: Revocable revocable_; }; public: explicit TaskFactory(T* object) : object_(object) { } template <typename TaskParamType, typename... Args> - inline TaskParamType* NewTask(Args&&... args) + inline already_AddRefed<TaskParamType> NewTask(Args&&... args) { typedef TaskWrapper<TaskParamType> TaskWrapper; - TaskWrapper* task = new TaskWrapper(this, mozilla::Forward<Args>(args)...); - return task; + RefPtr<TaskWrapper> task = + new TaskWrapper(this, mozilla::Forward<Args>(args)...); + return task.forget(); } template <class Method> - inline Task* NewRunnableMethod(Method method) { + inline already_AddRefed<Runnable> NewRunnableMethod(Method method) { typedef TaskWrapper<RunnableMethod<Method, Tuple0> > TaskWrapper; - TaskWrapper* task = new TaskWrapper(this); + RefPtr<TaskWrapper> task = new TaskWrapper(this); task->Init(object_, method, base::MakeTuple()); - return task; + return task.forget(); } template <class Method, class A> - inline Task* NewRunnableMethod(Method method, const A& a) { + inline already_AddRefed<Runnable> NewRunnableMethod(Method method, const A& a) { typedef TaskWrapper<RunnableMethod<Method, Tuple1<A> > > TaskWrapper; - TaskWrapper* task = new TaskWrapper(this); + RefPtr<TaskWrapper> task = new TaskWrapper(this); task->Init(object_, method, base::MakeTuple(a)); - return task; + return task.forget(); } protected: template <class Method, class Params> - class RunnableMethod : public Task { + class RunnableMethod : public Runnable { public: RunnableMethod() { } void Init(T* obj, Method meth, const Params& params) { obj_ = obj; meth_ = meth; params_ = params; } - virtual void Run() { DispatchToMethod(obj_, meth_, params_); } + NS_IMETHOD Run() override { + DispatchToMethod(obj_, meth_, params_); + return NS_OK; + } private: T* obj_; Method meth_; Params params_; }; private:
--- a/gfx/layers/AtomicRefCountedWithFinalize.h +++ b/gfx/layers/AtomicRefCountedWithFinalize.h @@ -146,17 +146,16 @@ private: derived->Finalize(); if (MOZ_LIKELY(!mMessageLoopToPostDestructionTo)) { delete derived; } else { if (MOZ_LIKELY(NS_IsMainThread())) { delete derived; } else { mMessageLoopToPostDestructionTo->PostTask( - FROM_HERE, NewRunnableFunction(&DestroyToBeCalledOnMainThread, derived)); } } } else if (1 == currCount && recycleCallback) { // There is nothing enforcing this in the code, except how the callers // are being careful to never let the reference count go down if there // is a callback. MOZ_ASSERT(!IsDead());
--- a/gfx/layers/apz/public/GeckoContentController.h +++ b/gfx/layers/apz/public/GeckoContentController.h @@ -9,19 +9,20 @@ #include "FrameMetrics.h" // for FrameMetrics, etc #include "Units.h" // for CSSPoint, CSSRect, etc #include "mozilla/Assertions.h" // for MOZ_ASSERT_HELPER2 #include "mozilla/EventForwards.h" // for Modifiers #include "nsISupportsImpl.h" #include "ThreadSafeRefcountingWithMainThreadDestruction.h" -class Task; +namespace mozilla { -namespace mozilla { +class Runnable; + namespace layers { class GeckoContentController { public: /** * At least one class deriving from GeckoContentController needs to do * synchronous cleanup on the main thread, so we use @@ -64,17 +65,17 @@ public: const ScrollableLayerGuid& aGuid, uint64_t aInputBlockId) = 0; /** * Schedules a runnable to run on the controller/UI thread at some time * in the future. * This method must always be called on the controller thread. */ - virtual void PostDelayedTask(Task* aTask, int aDelayMs) = 0; + virtual void PostDelayedTask(already_AddRefed<Runnable> aRunnable, int aDelayMs) = 0; /** * APZ uses |FrameMetrics::mCompositionBounds| for hit testing. Sometimes, * widget code has knowledge of a touch-sensitive region that should * additionally constrain hit testing for all frames associated with the * controller. This method allows APZ to query the controller for such a * region. A return value of true indicates that the controller has such a * region, and it is returned in |aOutRegion|.
--- a/gfx/layers/apz/src/AsyncPanZoomAnimation.h +++ b/gfx/layers/apz/src/AsyncPanZoomAnimation.h @@ -41,17 +41,17 @@ public: return DoSample(aFrameMetrics, aDelta); } /** * Get the deferred tasks in |mDeferredTasks| and place them in |aTasks|. See * |mDeferredTasks| for more information. Clears |mDeferredTasks|. */ - nsTArray<Task*> TakeDeferredTasks() { + nsTArray<RefPtr<Runnable>> TakeDeferredTasks() { return Move(mDeferredTasks); } virtual WheelScrollAnimation* AsWheelScrollAnimation() { return nullptr; } virtual SmoothScrollAnimation* AsSmoothScrollAnimation() { return nullptr; @@ -66,15 +66,15 @@ protected: virtual ~AsyncPanZoomAnimation() { } /** * Tasks scheduled for execution after the APZC's mMonitor is released. * Derived classes can add tasks here in Sample(), and the APZC can call * ExecuteDeferredTasks() to execute them. */ - nsTArray<Task*> mDeferredTasks; + nsTArray<RefPtr<Runnable>> mDeferredTasks; }; } // namespace layers } // namespace mozilla #endif // mozilla_layers_AsyncPanZoomAnimation_h_
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -18,17 +18,16 @@ #include "InputData.h" // for MultiTouchInput, etc #include "InputBlockState.h" // for InputBlockState, TouchBlockState #include "InputQueue.h" // for InputQueue #include "OverscrollHandoffState.h" // for OverscrollHandoffState #include "Units.h" // for CSSRect, CSSPoint, etc #include "UnitTransforms.h" // for TransformTo #include "base/message_loop.h" // for MessageLoop #include "base/task.h" // for NewRunnableMethod, etc -#include "base/tracked.h" // for FROM_HERE #include "gfxPrefs.h" // for gfxPrefs #include "gfxTypes.h" // for gfxFloat #include "LayersLogging.h" // for print_stderr #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc #include "mozilla/BasicEvents.h" // for Modifiers, MODIFIER_* #include "mozilla/ClearOnShutdown.h" // for ClearOnShutdown #include "mozilla/ComputedTimingFunction.h" // for ComputedTimingFunction #include "mozilla/EventForwards.h" // for nsEventStatus_* @@ -3057,17 +3056,17 @@ AsyncPanZoomController::RequestContentRe } controller->RequestContentRepaint(aFrameMetrics); mExpectedGeckoMetrics = aFrameMetrics; mLastPaintRequestMetrics = aFrameMetrics; } bool AsyncPanZoomController::UpdateAnimation(const TimeStamp& aSampleTime, - nsTArray<Task*>* aOutDeferredTasks) + nsTArray<RefPtr<Runnable>>* aOutDeferredTasks) { APZThreadUtils::AssertOnCompositorThread(); // This function may get called multiple with the same sample time, because // there may be multiple layers with this APZC, and each layer invokes this // function during composition. However we only want to do one animation step // per composition so we need to deduplicate these calls first. if (mLastSampleTime == aSampleTime) { @@ -3158,17 +3157,17 @@ bool AsyncPanZoomController::AdvanceAnim // The eventual return value of this function. The compositor needs to know // whether or not to advance by a frame as soon as it can. For example, if a // fling is happening, it has to keep compositing so that the animation is // smooth. If an animation frame is requested, it is the compositor's // responsibility to schedule a composite. mAsyncTransformAppliedToContent = false; bool requestAnimationFrame = false; - nsTArray<Task*> deferredTasks; + nsTArray<RefPtr<Runnable>> deferredTasks; { ReentrantMonitorAutoEnter lock(mMonitor); requestAnimationFrame = UpdateAnimation(aSampleTime, &deferredTasks); { // scope lock MutexAutoLock lock(mCheckerboardEventLock); @@ -3182,17 +3181,17 @@ bool AsyncPanZoomController::AdvanceAnim } // Execute any deferred tasks queued up by mAnimation's Sample() (called by // UpdateAnimation()). This needs to be done after the monitor is released // since the tasks are allowed to call APZCTreeManager methods which can grab // the tree lock. for (uint32_t i = 0; i < deferredTasks.Length(); ++i) { deferredTasks[i]->Run(); - delete deferredTasks[i]; + deferredTasks[i] = nullptr; } // One of the deferred tasks may have started a new animation. In this case, // we want to ask the compositor to schedule a new composite. requestAnimationFrame |= (mAnimation != nullptr); return requestAnimationFrame; } @@ -3847,22 +3846,23 @@ void AsyncPanZoomController::UpdateZoomC ZoomConstraints AsyncPanZoomController::GetZoomConstraints() const { return mZoomConstraints; } -void AsyncPanZoomController::PostDelayedTask(Task* aTask, int aDelayMs) { +void AsyncPanZoomController::PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs) { APZThreadUtils::AssertOnControllerThread(); RefPtr<GeckoContentController> controller = GetGeckoContentController(); if (controller) { - controller->PostDelayedTask(aTask, aDelayMs); + controller->PostDelayedTask(Move(aTask), aDelayMs); } + // XXX khuey what is supposed to happen if there's no controller? We were leaking tasks ... } bool AsyncPanZoomController::Matches(const ScrollableLayerGuid& aGuid) { return aGuid == GetGuid(); } bool AsyncPanZoomController::HasTreeManager(const APZCTreeManager* aTreeManager) const
--- a/gfx/layers/apz/src/AsyncPanZoomController.h +++ b/gfx/layers/apz/src/AsyncPanZoomController.h @@ -141,33 +141,33 @@ public: * or in UpdateZoomConstraints()). */ ZoomConstraints GetZoomConstraints() const; /** * Schedules a runnable to run on the controller/UI thread at some time * in the future. */ - void PostDelayedTask(Task* aTask, int aDelayMs); + void PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs); // -------------------------------------------------------------------------- // These methods must only be called on the compositor thread. // /** * Advances any animations currently running to the given timestamp. * This may be called multiple times with the same timestamp. * * The return value indicates whether or not any currently running animation * should continue. If true, the compositor should schedule another composite. */ bool AdvanceAnimations(const TimeStamp& aSampleTime); bool UpdateAnimation(const TimeStamp& aSampleTime, - nsTArray<Task*>* aOutDeferredTasks); + nsTArray<RefPtr<Runnable>>* aOutDeferredTasks); /** * A shadow layer update has arrived. |aScrollMetdata| is the new ScrollMetadata * for the container layer corresponding to this APZC. * |aIsFirstPaint| is a flag passed from the shadow * layers code indicating that the scroll metadata being sent with this call are * the initial metadata and the initial paint of the frame has just happened. */
--- a/gfx/layers/apz/src/GestureEventListener.cpp +++ b/gfx/layers/apz/src/GestureEventListener.cpp @@ -492,21 +492,22 @@ void GestureEventListener::CancelLongTap if (mLongTapTimeoutTask) { mLongTapTimeoutTask->Cancel(); mLongTapTimeoutTask = nullptr; } } void GestureEventListener::CreateLongTapTimeoutTask() { - mLongTapTimeoutTask = + RefPtr<CancelableRunnable> task = NewRunnableMethod(this, &GestureEventListener::HandleInputTimeoutLongTap); + mLongTapTimeoutTask = task; mAsyncPanZoomController->PostDelayedTask( - mLongTapTimeoutTask, + task.forget(), gfxPrefs::UiClickHoldContextMenusDelay()); } void GestureEventListener::CancelMaxTapTimeoutTask() { if (mState == GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN) { // being in this state means the timer has just been triggered return; @@ -518,19 +519,20 @@ void GestureEventListener::CancelMaxTapT } } void GestureEventListener::CreateMaxTapTimeoutTask() { mLastTapInput = mLastTouchInput; TouchBlockState* block = mAsyncPanZoomController->GetInputQueue()->CurrentTouchBlock(); - mMaxTapTimeoutTask = + RefPtr<CancelableRunnable> task = NewRunnableMethod(this, &GestureEventListener::HandleInputTimeoutMaxTap, block->IsDuringFastFling()); + mMaxTapTimeoutTask = task; mAsyncPanZoomController->PostDelayedTask( - mMaxTapTimeoutTask, + task.forget(), MAX_TAP_TIME); } } // namespace layers } // namespace mozilla
--- a/gfx/layers/apz/src/GestureEventListener.h +++ b/gfx/layers/apz/src/GestureEventListener.h @@ -9,19 +9,20 @@ #include "InputData.h" // for MultiTouchInput, etc #include "Units.h" #include "mozilla/EventForwards.h" // for nsEventStatus #include "mozilla/RefPtr.h" // for RefPtr #include "nsISupportsImpl.h" #include "nsTArray.h" // for nsTArray -class CancelableTask; +namespace mozilla { -namespace mozilla { +class CancelableRunnable; + namespace layers { class AsyncPanZoomController; /** * Platform-non-specific, generalized gesture event listener. This class * intercepts all touches events on their way to AsyncPanZoomController and * determines whether or not they are part of a gesture. @@ -209,30 +210,30 @@ private: * we can cancel it if any other touch event happens. * * The task is supposed to be non-null if in GESTURE_FIRST_SINGLE_TOUCH_DOWN * and GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN states. * * CancelLongTapTimeoutTask: Cancel the mLongTapTimeoutTask and also set * it to null. */ - CancelableTask *mLongTapTimeoutTask; + RefPtr<CancelableRunnable> mLongTapTimeoutTask; void CancelLongTapTimeoutTask(); void CreateLongTapTimeoutTask(); /** * Task used to timeout a single tap or a double tap. * * The task is supposed to be non-null if in GESTURE_FIRST_SINGLE_TOUCH_DOWN, * GESTURE_FIRST_SINGLE_TOUCH_UP and GESTURE_SECOND_SINGLE_TOUCH_DOWN states. * * CancelMaxTapTimeoutTask: Cancel the mMaxTapTimeoutTask and also set * it to null. */ - CancelableTask *mMaxTapTimeoutTask; + RefPtr<CancelableRunnable> mMaxTapTimeoutTask; void CancelMaxTapTimeoutTask(); void CreateMaxTapTimeoutTask(); }; } // namespace layers } // namespace mozilla #endif
--- a/gfx/layers/apz/test/gtest/APZTestCommon.h +++ b/gfx/layers/apz/test/gtest/APZTestCommon.h @@ -36,18 +36,16 @@ using namespace mozilla::gfx; using namespace mozilla::layers; using ::testing::_; using ::testing::NiceMock; using ::testing::AtLeast; using ::testing::AtMost; using ::testing::MockFunction; using ::testing::InSequence; -class Task; - template<class T> class ScopedGfxPref { public: ScopedGfxPref(T (*aGetPrefFunc)(void), void (*aSetPrefFunc)(T), T aVal) : mSetPrefFunc(aSetPrefFunc) { mOldVal = aGetPrefFunc(); aSetPrefFunc(aVal); @@ -76,17 +74,20 @@ static TimeStamp GetStartupTime() { class MockContentController : public GeckoContentController { public: MOCK_METHOD1(RequestContentRepaint, void(const FrameMetrics&)); MOCK_METHOD2(RequestFlingSnap, void(const FrameMetrics::ViewID& aScrollId, const mozilla::CSSPoint& aDestination)); MOCK_METHOD2(AcknowledgeScrollUpdate, void(const FrameMetrics::ViewID&, const uint32_t& aScrollGeneration)); MOCK_METHOD3(HandleDoubleTap, void(const CSSPoint&, Modifiers, const ScrollableLayerGuid&)); MOCK_METHOD3(HandleSingleTap, void(const CSSPoint&, Modifiers, const ScrollableLayerGuid&)); MOCK_METHOD4(HandleLongTap, void(const CSSPoint&, Modifiers, const ScrollableLayerGuid&, uint64_t)); - MOCK_METHOD2(PostDelayedTask, void(Task* aTask, int aDelayMs)); + // Can't use the macros with already_AddRefed :( + void PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs) { + RefPtr<Runnable> task = aTask; + } MOCK_METHOD3(NotifyAPZStateChange, void(const ScrollableLayerGuid& aGuid, APZStateChange aChange, int aArg)); MOCK_METHOD0(NotifyFlushComplete, void()); }; class MockContentControllerDelayed : public MockContentController { public: MockContentControllerDelayed() : mTime(GetStartupTime()) @@ -104,62 +105,63 @@ public: void AdvanceBy(const TimeDuration& aIncrement) { TimeStamp target = mTime + aIncrement; while (mTaskQueue.Length() > 0 && mTaskQueue[0].second <= target) { RunNextDelayedTask(); } mTime = target; } - void PostDelayedTask(Task* aTask, int aDelayMs) { + void PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs) { + RefPtr<Runnable> task = aTask; TimeStamp runAtTime = mTime + TimeDuration::FromMilliseconds(aDelayMs); int insIndex = mTaskQueue.Length(); while (insIndex > 0) { if (mTaskQueue[insIndex - 1].second <= runAtTime) { break; } insIndex--; } - mTaskQueue.InsertElementAt(insIndex, std::make_pair(aTask, runAtTime)); + mTaskQueue.InsertElementAt(insIndex, std::make_pair(task, runAtTime)); } // Run all the tasks in the queue, returning the number of tasks // run. Note that if a task queues another task while running, that // new task will not be run. Therefore, there may be still be tasks // in the queue after this function is called. Only when the return // value is 0 is the queue guaranteed to be empty. int RunThroughDelayedTasks() { - nsTArray<std::pair<Task*, TimeStamp>> runQueue; + nsTArray<std::pair<RefPtr<Runnable>, TimeStamp>> runQueue; runQueue.SwapElements(mTaskQueue); int numTasks = runQueue.Length(); for (int i = 0; i < numTasks; i++) { mTime = runQueue[i].second; runQueue[i].first->Run(); // Deleting the task is important in order to release the reference to // the callee object. - delete runQueue[i].first; + runQueue[i].first = nullptr; } return numTasks; } private: void RunNextDelayedTask() { - std::pair<Task*, TimeStamp> next = mTaskQueue[0]; + std::pair<RefPtr<Runnable>, TimeStamp> next = mTaskQueue[0]; mTaskQueue.RemoveElementAt(0); mTime = next.second; next.first->Run(); // Deleting the task is important in order to release the reference to // the callee object. - delete next.first; + next.first = nullptr; } // The following array is sorted by timestamp (tasks are inserted in order by // timestamp). - nsTArray<std::pair<Task*, TimeStamp>> mTaskQueue; + nsTArray<std::pair<RefPtr<Runnable>, TimeStamp>> mTaskQueue; TimeStamp mTime; }; class TestAPZCTreeManager : public APZCTreeManager { public: explicit TestAPZCTreeManager(MockContentControllerDelayed* aMcc) : mcc(aMcc) {} RefPtr<InputQueue> GetInputQueue() const {
--- a/gfx/layers/apz/util/APZThreadUtils.cpp +++ b/gfx/layers/apz/util/APZThreadUtils.cpp @@ -48,54 +48,53 @@ APZThreadUtils::AssertOnControllerThread APZThreadUtils::AssertOnCompositorThread() { if (GetThreadAssertionsEnabled()) { Compositor::AssertOnCompositorThread(); } } /*static*/ void -APZThreadUtils::RunOnControllerThread(Task* aTask) +APZThreadUtils::RunOnControllerThread(already_AddRefed<Runnable> aTask) { + RefPtr<Runnable> task = aTask; + #ifdef MOZ_ANDROID_APZ // This is needed while nsWindow::ConfigureAPZControllerThread is not propper // implemented. if (AndroidBridge::IsJavaUiThread()) { - aTask->Run(); - delete aTask; + task->Run(); } else { - AndroidBridge::Bridge()->PostTaskToUiThread(aTask, 0); + AndroidBridge::Bridge()->PostTaskToUiThread(task.forget(), 0); } #else if (!sControllerThread) { // Could happen on startup NS_WARNING("Dropping task posted to controller thread"); - delete aTask; return; } if (sControllerThread == MessageLoop::current()) { - aTask->Run(); - delete aTask; + task->Run(); } else { - sControllerThread->PostTask(FROM_HERE, aTask); + sControllerThread->PostTask(task.forget()); } #endif } /*static*/ void -APZThreadUtils::RunDelayedTaskOnCurrentThread(Task* aTask, +APZThreadUtils::RunDelayedTaskOnCurrentThread(already_AddRefed<Runnable> aTask, const TimeDuration& aDelay) { if (MessageLoop* messageLoop = MessageLoop::current()) { - messageLoop->PostDelayedTask(FROM_HERE, aTask, aDelay.ToMilliseconds()); + messageLoop->PostDelayedTask(Move(aTask), aDelay.ToMilliseconds()); } else { #ifdef MOZ_ANDROID_APZ // Fennec does not have a MessageLoop::current() on the controller thread. - AndroidBridge::Bridge()->PostTaskToUiThread(aTask, aDelay.ToMilliseconds()); + AndroidBridge::Bridge()->PostTaskToUiThread(Move(aTask), aDelay.ToMilliseconds()); #else // Other platforms should. MOZ_RELEASE_ASSERT(false, "This non-Fennec platform should have a MessageLoop::current()"); #endif } } /*static*/ bool
--- a/gfx/layers/apz/util/APZThreadUtils.h +++ b/gfx/layers/apz/util/APZThreadUtils.h @@ -5,19 +5,20 @@ #ifndef mozilla_layers_APZThreadUtils_h #define mozilla_layers_APZThreadUtils_h #include "base/message_loop.h" #include "mozilla/TimeStamp.h" // for TimeDuration #include "nsITimer.h" -class Task; +namespace mozilla { -namespace mozilla { +class Runnable; + namespace layers { class APZThreadUtils { public: /** * In the gtest environment everything runs on one thread, so we * shouldn't assert that we're on a particular thread. This enables @@ -45,22 +46,22 @@ public: */ static void AssertOnCompositorThread(); /** * Run the given task on the APZ "controller thread" for this platform. If * this function is called from the controller thread itself then the task is * run immediately without getting queued. */ - static void RunOnControllerThread(Task* aTask); + static void RunOnControllerThread(already_AddRefed<Runnable> aTask); /** * Runs the given task on the current thread after a delay of |aDelay|. */ - static void RunDelayedTaskOnCurrentThread(Task* aTask, + static void RunDelayedTaskOnCurrentThread(already_AddRefed<Runnable> aTask, const TimeDuration& aDelay); /** * Returns true if currently on APZ "controller thread". */ static bool IsControllerThread(); };
--- a/gfx/layers/apz/util/ActiveElementManager.cpp +++ b/gfx/layers/apz/util/ActiveElementManager.cpp @@ -89,20 +89,20 @@ ActiveElementManager::TriggerElementActi // Otherwise, wait a bit to see if the user will pan or not. if (!mCanBePan) { SetActive(mTarget); } else { CancelTask(); // this is only needed because of bug 1169802. Fixing that // bug properly should make this unnecessary. MOZ_ASSERT(mSetActiveTask == nullptr); - mSetActiveTask = NewRunnableMethod( + RefPtr<CancelableRunnable> task = NewRunnableMethod( this, &ActiveElementManager::SetActiveTask, mTarget); - MessageLoop::current()->PostDelayedTask( - FROM_HERE, mSetActiveTask, sActivationDelayMs); + mSetActiveTask = task; + MessageLoop::current()->PostDelayedTask(task.forget(), sActivationDelayMs); AEM_LOG("Scheduling mSetActiveTask %p\n", mSetActiveTask); } } void ActiveElementManager::ClearActivation() { AEM_LOG("Clearing element activation\n");
--- a/gfx/layers/apz/util/ActiveElementManager.h +++ b/gfx/layers/apz/util/ActiveElementManager.h @@ -4,19 +4,20 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef mozilla_layers_ActiveElementManager_h #define mozilla_layers_ActiveElementManager_h #include "nsCOMPtr.h" #include "nsISupportsImpl.h" -class CancelableTask; +namespace mozilla { -namespace mozilla { +class CancelableRunnable; + namespace dom { class Element; class EventTarget; } // namespace dom namespace layers { /** @@ -77,17 +78,17 @@ private: * Whether mCanBePan has been set for the current touch block. * We need to keep track of this to allow HandleTouchStart() and * SetTargetElement() to be called in either order. */ bool mCanBePanSet; /** * A task for calling SetActive() after a timeout. */ - CancelableTask* mSetActiveTask; + RefPtr<CancelableRunnable> mSetActiveTask; /** * See ActiveElementUsesStyle() documentation. */ bool mActiveElementUsesStyle; // Helpers void TriggerElementActivation(); void SetActive(dom::Element* aTarget);
--- a/gfx/layers/apz/util/ChromeProcessController.cpp +++ b/gfx/layers/apz/util/ChromeProcessController.cpp @@ -32,17 +32,16 @@ ChromeProcessController::ChromeProcessCo , mUILoop(MessageLoop::current()) { // Otherwise we're initializing mUILoop incorrectly. MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aAPZEventState); MOZ_ASSERT(aAPZCTreeManager); mUILoop->PostTask( - FROM_HERE, NewRunnableMethod(this, &ChromeProcessController::InitializeRoot)); } ChromeProcessController::~ChromeProcessController() {} void ChromeProcessController::InitializeRoot() { @@ -58,27 +57,26 @@ ChromeProcessController::RequestContentR if (metrics.IsRootContent()) { APZCCallbackHelper::UpdateRootFrame(metrics); } else { APZCCallbackHelper::UpdateSubFrame(metrics); } } void -ChromeProcessController::PostDelayedTask(Task* aTask, int aDelayMs) +ChromeProcessController::PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs) { - MessageLoop::current()->PostDelayedTask(FROM_HERE, aTask, aDelayMs); + MessageLoop::current()->PostDelayedTask(Move(aTask), aDelayMs); } void ChromeProcessController::Destroy() { if (MessageLoop::current() != mUILoop) { mUILoop->PostTask( - FROM_HERE, NewRunnableMethod(this, &ChromeProcessController::Destroy)); return; } MOZ_ASSERT(MessageLoop::current() == mUILoop); mWidget = nullptr; } @@ -119,17 +117,16 @@ ChromeProcessController::GetRootContentD void ChromeProcessController::HandleDoubleTap(const mozilla::CSSPoint& aPoint, Modifiers aModifiers, const ScrollableLayerGuid& aGuid) { if (MessageLoop::current() != mUILoop) { mUILoop->PostTask( - FROM_HERE, NewRunnableMethod(this, &ChromeProcessController::HandleDoubleTap, aPoint, aModifiers, aGuid)); return; } nsCOMPtr<nsIDocument> document = GetRootContentDocument(aGuid.mScrollId); if (!document.get()) { return; @@ -157,64 +154,60 @@ ChromeProcessController::HandleDoubleTap void ChromeProcessController::HandleSingleTap(const CSSPoint& aPoint, Modifiers aModifiers, const ScrollableLayerGuid& aGuid) { if (MessageLoop::current() != mUILoop) { mUILoop->PostTask( - FROM_HERE, NewRunnableMethod(this, &ChromeProcessController::HandleSingleTap, aPoint, aModifiers, aGuid)); return; } mAPZEventState->ProcessSingleTap(aPoint, aModifiers, aGuid); } void ChromeProcessController::HandleLongTap(const mozilla::CSSPoint& aPoint, Modifiers aModifiers, const ScrollableLayerGuid& aGuid, uint64_t aInputBlockId) { if (MessageLoop::current() != mUILoop) { mUILoop->PostTask( - FROM_HERE, NewRunnableMethod(this, &ChromeProcessController::HandleLongTap, aPoint, aModifiers, aGuid, aInputBlockId)); return; } mAPZEventState->ProcessLongTap(GetPresShell(), aPoint, aModifiers, aGuid, aInputBlockId); } void ChromeProcessController::NotifyAPZStateChange(const ScrollableLayerGuid& aGuid, APZStateChange aChange, int aArg) { if (MessageLoop::current() != mUILoop) { mUILoop->PostTask( - FROM_HERE, NewRunnableMethod(this, &ChromeProcessController::NotifyAPZStateChange, aGuid, aChange, aArg)); return; } mAPZEventState->ProcessAPZStateChange(GetRootDocument(), aGuid.mScrollId, aChange, aArg); } void ChromeProcessController::NotifyMozMouseScrollEvent(const FrameMetrics::ViewID& aScrollId, const nsString& aEvent) { if (MessageLoop::current() != mUILoop) { mUILoop->PostTask( - FROM_HERE, NewRunnableMethod(this, &ChromeProcessController::NotifyMozMouseScrollEvent, aScrollId, aEvent)); return; } APZCCallbackHelper::NotifyMozMouseScrollEvent(aScrollId, aEvent); } void
--- a/gfx/layers/apz/util/ChromeProcessController.h +++ b/gfx/layers/apz/util/ChromeProcessController.h @@ -34,17 +34,17 @@ protected: public: explicit ChromeProcessController(nsIWidget* aWidget, APZEventState* aAPZEventState, APZCTreeManager* aAPZCTreeManager); ~ChromeProcessController(); virtual void Destroy() override; // GeckoContentController interface virtual void RequestContentRepaint(const FrameMetrics& aFrameMetrics) override; - virtual void PostDelayedTask(Task* aTask, int aDelayMs) override; + virtual void PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs) override; virtual void HandleDoubleTap(const mozilla::CSSPoint& aPoint, Modifiers aModifiers, const ScrollableLayerGuid& aGuid) override; virtual void HandleSingleTap(const mozilla::CSSPoint& aPoint, Modifiers aModifiers, const ScrollableLayerGuid& aGuid) override; virtual void HandleLongTap(const mozilla::CSSPoint& aPoint, Modifiers aModifiers, const ScrollableLayerGuid& aGuid, uint64_t aInputBlockId) override; virtual void NotifyAPZStateChange(const ScrollableLayerGuid& aGuid,
--- a/gfx/layers/client/CompositableClient.cpp +++ b/gfx/layers/client/CompositableClient.cpp @@ -59,20 +59,20 @@ public: void RemoveTextureFromCompositableTracker::ReleaseTextureClient() { if (mTextureClient && mTextureClient->GetAllocator() && !mTextureClient->GetAllocator()->UsesImageBridge()) { - TextureClientReleaseTask* task = new TextureClientReleaseTask(mTextureClient); + RefPtr<TextureClientReleaseTask> task = new TextureClientReleaseTask(mTextureClient); RefPtr<ClientIPCAllocator> allocator = mTextureClient->GetAllocator(); mTextureClient = nullptr; - allocator->AsClientAllocator()->GetMessageLoop()->PostTask(FROM_HERE, task); + allocator->AsClientAllocator()->GetMessageLoop()->PostTask(task.forget()); } else { mTextureClient = nullptr; } } /* static */ void CompositableClient::TransactionCompleteted(PCompositableChild* aActor, uint64_t aTransactionId) {
--- a/gfx/layers/client/TextureClient.cpp +++ b/gfx/layers/client/TextureClient.cpp @@ -250,25 +250,24 @@ DeallocateTextureClient(TextureDeallocPa } // First make sure that the work is happening on the IPDL thread. if (ipdlMsgLoop && MessageLoop::current() != ipdlMsgLoop) { if (params.syncDeallocation) { bool done = false; ReentrantMonitor barrier("DeallocateTextureClient"); ReentrantMonitorAutoEnter autoMon(barrier); - ipdlMsgLoop->PostTask(FROM_HERE, - NewRunnableFunction(DeallocateTextureClientSyncProxy, - params, &barrier, &done)); + ipdlMsgLoop->PostTask(NewRunnableFunction(DeallocateTextureClientSyncProxy, + params, &barrier, &done)); while (!done) { barrier.Wait(); } } else { - ipdlMsgLoop->PostTask(FROM_HERE, - NewRunnableFunction(DeallocateTextureClient, params)); + ipdlMsgLoop->PostTask(NewRunnableFunction(DeallocateTextureClient, + params)); } // The work has been forwarded to the IPDL thread, we are done. return; } // Below this line, we are either in the IPDL thread or ther is no IPDL // thread anymore.
--- a/gfx/layers/client/TextureClient.h +++ b/gfx/layers/client/TextureClient.h @@ -656,26 +656,27 @@ public: // Pointer to the pool this tile came from. TextureClientPool* mPoolTracker; #endif }; /** * Task that releases TextureClient pointer on a specified thread. */ -class TextureClientReleaseTask : public Task +class TextureClientReleaseTask : public Runnable { public: explicit TextureClientReleaseTask(TextureClient* aClient) : mTextureClient(aClient) { } - virtual void Run() override + NS_IMETHOD Run() override { mTextureClient = nullptr; + return NS_OK; } private: RefPtr<TextureClient> mTextureClient; }; // Automatically lock and unlock a texture. Since texture locking is fallible, // Succeeded() must be checked on the guard object before proceeding.
--- a/gfx/layers/client/TextureClientRecycleAllocator.cpp +++ b/gfx/layers/client/TextureClientRecycleAllocator.cpp @@ -88,27 +88,28 @@ TextureClientRecycleAllocator::~TextureC } void TextureClientRecycleAllocator::SetMaxPoolSize(uint32_t aMax) { mMaxPooledSize = aMax; } -class TextureClientRecycleTask : public Task +class TextureClientRecycleTask : public Runnable { public: explicit TextureClientRecycleTask(TextureClient* aClient, TextureFlags aFlags) : mTextureClient(aClient) , mFlags(aFlags) {} - virtual void Run() override + NS_IMETHOD Run() override { mTextureClient->RecycleTexture(mFlags); + return NS_OK; } private: RefPtr<TextureClient> mTextureClient; TextureFlags mFlags; }; already_AddRefed<TextureClient> @@ -141,27 +142,27 @@ TextureClientRecycleAllocator::CreateOrR RefPtr<TextureClientHolder> textureHolder; { MutexAutoLock lock(mLock); if (!mPooledClients.empty()) { textureHolder = mPooledClients.top(); mPooledClients.pop(); - Task* task = nullptr; + RefPtr<Runnable> task; // If a pooled TextureClient is not compatible, release it. if (!aHelper.IsCompatible(textureHolder->GetTextureClient())) { // Release TextureClient. task = new TextureClientReleaseTask(textureHolder->GetTextureClient()); textureHolder->ClearTextureClient(); textureHolder = nullptr; } else { task = new TextureClientRecycleTask(textureHolder->GetTextureClient(), aHelper.mTextureFlags); } - mSurfaceAllocator->GetMessageLoop()->PostTask(FROM_HERE, task); + mSurfaceAllocator->GetMessageLoop()->PostTask(task.forget()); } } if (!textureHolder) { // Allocate new TextureClient RefPtr<TextureClient> texture = aHelper.Allocate(mSurfaceAllocator); if (!texture) { return nullptr;
--- a/gfx/layers/ipc/CompositorBridgeChild.cpp +++ b/gfx/layers/ipc/CompositorBridgeChild.cpp @@ -5,17 +5,16 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mozilla/layers/CompositorBridgeChild.h" #include "mozilla/layers/CompositorBridgeParent.h" #include <stddef.h> // for size_t #include "ClientLayerManager.h" // for ClientLayerManager #include "base/message_loop.h" // for MessageLoop #include "base/task.h" // for NewRunnableMethod, etc -#include "base/tracked.h" // for FROM_HERE #include "mozilla/layers/LayerTransactionChild.h" #include "mozilla/layers/PLayerTransactionChild.h" #include "mozilla/mozalloc.h" // for operator new, etc #include "nsDebug.h" // for NS_RUNTIMEABORT #include "nsIObserver.h" // for nsIObserver #include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc #include "nsTArray.h" // for nsTArray, nsTArray_Impl #include "nsXULAppAPI.h" // for XRE_GetIOMessageLoop, etc @@ -41,18 +40,18 @@ Atomic<int32_t> CompositableForwarder::s CompositorBridgeChild::CompositorBridgeChild(ClientLayerManager *aLayerManager) : mLayerManager(aLayerManager) , mCanSend(false) { } CompositorBridgeChild::~CompositorBridgeChild() { - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, - new DeleteTask<Transport>(GetTransport())); + RefPtr<DeleteTask<Transport>> task = new DeleteTask<Transport>(GetTransport()); + XRE_GetIOMessageLoop()->PostTask(task.forget()); if (mCanSend) { gfxCriticalError() << "CompositorBridgeChild was not deinitialized"; } } bool CompositorBridgeChild::IsSameProcess() const @@ -106,17 +105,17 @@ CompositorBridgeChild::Destroy() // CompositorBridgeParent to the CompositorBridgeChild (e.g. caused by the destruction // of shared memory). We need to ensure this gets processed by the // CompositorBridgeChild before it gets destroyed. It suffices to ensure that // events already in the MessageLoop get processed before the // CompositorBridgeChild is destroyed, so we add a task to the MessageLoop to // handle compositor desctruction. // From now on we can't send any message message. - MessageLoop::current()->PostTask(FROM_HERE, + MessageLoop::current()->PostTask( NewRunnableFunction(DeferredDestroyCompositor, mCompositorBridgeParent, selfRef)); } // static void CompositorBridgeChild::ShutDown() { if (sCompositorBridge) {
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp +++ b/gfx/layers/ipc/CompositorBridgeParent.cpp @@ -10,17 +10,16 @@ #include <map> // for _Rb_tree_iterator, etc #include <utility> // for pair #include "LayerTransactionParent.h" // for LayerTransactionParent #include "RenderTrace.h" // for RenderTraceLayers #include "base/message_loop.h" // for MessageLoop #include "base/process.h" // for ProcessId #include "base/task.h" // for CancelableTask, etc #include "base/thread.h" // for Thread -#include "base/tracked.h" // for FROM_HERE #include "gfxContext.h" // for gfxContext #include "gfxPlatform.h" // for gfxPlatform #ifdef MOZ_WIDGET_GTK #include "gfxPlatformGtk.h" // for gfxPlatform #endif #include "gfxPrefs.h" // for gfxPrefs #include "mozilla/AutoRestore.h" // for AutoRestore #include "mozilla/ClearOnShutdown.h" // for ClearOnShutdown @@ -357,20 +356,20 @@ CompositorVsyncScheduler::~CompositorVsy void CompositorVsyncScheduler::SetDisplay(bool aDisplayEnable) { // SetDisplay() is usually called from nsScreenManager at main thread. Post // to compositor thread if needs. if (!CompositorBridgeParent::IsInCompositorThread()) { MOZ_ASSERT(NS_IsMainThread()); MonitorAutoLock lock(mSetDisplayMonitor); - mSetDisplayTask = NewRunnableMethod(this, - &CompositorVsyncScheduler::SetDisplay, - aDisplayEnable); - ScheduleTask(mSetDisplayTask, 0); + RefPtr<CancelableRunnable> task = + NewRunnableMethod(this, &CompositorVsyncScheduler::SetDisplay, aDisplayEnable); + mSetDisplayTask = task; + ScheduleTask(task.forget(), 0); return; } else { MonitorAutoLock lock(mSetDisplayMonitor); mSetDisplayTask = nullptr; } if (mDisplayEnabled == aDisplayEnable) { return; @@ -422,20 +421,21 @@ CompositorVsyncScheduler::Destroy() } void CompositorVsyncScheduler::PostCompositeTask(TimeStamp aCompositeTimestamp) { // can be called from the compositor or vsync thread MonitorAutoLock lock(mCurrentCompositeTaskMonitor); if (mCurrentCompositeTask == nullptr) { - mCurrentCompositeTask = NewRunnableMethod(this, - &CompositorVsyncScheduler::Composite, - aCompositeTimestamp); - ScheduleTask(mCurrentCompositeTask, 0); + RefPtr<CancelableRunnable> task = + NewRunnableMethod(this, &CompositorVsyncScheduler::Composite, + aCompositeTimestamp); + mCurrentCompositeTask = task; + ScheduleTask(task.forget(), 0); } } void CompositorVsyncScheduler::ScheduleComposition() { MOZ_ASSERT(CompositorBridgeParent::IsInCompositorThread()); if (mAsapScheduling) { @@ -475,19 +475,20 @@ CompositorVsyncScheduler::CancelCurrentS * next vsync? * How many skipped vsync events until we stop listening to vsync events? */ void CompositorVsyncScheduler::SetNeedsComposite() { if (!CompositorBridgeParent::IsInCompositorThread()) { MonitorAutoLock lock(mSetNeedsCompositeMonitor); - mSetNeedsCompositeTask = NewRunnableMethod(this, - &CompositorVsyncScheduler::SetNeedsComposite); - ScheduleTask(mSetNeedsCompositeTask, 0); + RefPtr<CancelableRunnable> task = + NewRunnableMethod(this, &CompositorVsyncScheduler::SetNeedsComposite); + mSetNeedsCompositeTask = task; + ScheduleTask(task.forget(), 0); return; } else { MonitorAutoLock lock(mSetNeedsCompositeMonitor); mSetNeedsCompositeTask = nullptr; } #ifdef MOZ_WIDGET_GONK #if ANDROID_VERSION >= 19 @@ -654,21 +655,22 @@ void CompositorBridgeParent::ShutDown() } MessageLoop* CompositorBridgeParent::CompositorLoop() { return CompositorThread() ? CompositorThread()->message_loop() : nullptr; } void -CompositorVsyncScheduler::ScheduleTask(CancelableTask* aTask, int aTime) +CompositorVsyncScheduler::ScheduleTask(already_AddRefed<CancelableRunnable> aTask, + int aTime) { MOZ_ASSERT(CompositorBridgeParent::CompositorLoop()); MOZ_ASSERT(aTime >= 0); - CompositorBridgeParent::CompositorLoop()->PostDelayedTask(FROM_HERE, aTask, aTime); + CompositorBridgeParent::CompositorLoop()->PostDelayedTask(Move(aTask), aTime); } void CompositorVsyncScheduler::ResumeComposition() { MOZ_ASSERT(CompositorBridgeParent::IsInCompositorThread()); mLastCompose = TimeStamp::Now(); ComposeToTarget(nullptr); @@ -709,20 +711,20 @@ CompositorBridgeParent::CompositorBridge MOZ_ASSERT(CompositorThread(), "The compositor thread must be Initialized before instanciating a CompositorBridgeParent."); MOZ_COUNT_CTOR(CompositorBridgeParent); mCompositorID = 0; // FIXME: This holds on the the fact that right now the only thing that // can destroy this instance is initialized on the compositor thread after // this task has been processed. MOZ_ASSERT(CompositorLoop()); - CompositorLoop()->PostTask(FROM_HERE, NewRunnableFunction(&AddCompositor, - this, &mCompositorID)); - - CompositorLoop()->PostTask(FROM_HERE, NewRunnableFunction(SetThreadPriority)); + CompositorLoop()->PostTask(NewRunnableFunction(&AddCompositor, + this, &mCompositorID)); + + CompositorLoop()->PostTask(NewRunnableFunction(SetThreadPriority)); { // scope lock MonitorAutoLock lock(*sIndirectLayerTreesLock); sIndirectLayerTrees[mRootLayerTreeID].mParent = this; } // The Compositor uses the APZ pref directly since it needs to know whether @@ -975,35 +977,32 @@ CompositorBridgeParent::ActorDestroy(Act mCompositorScheduler->Destroy(); // There are chances that the ref count reaches zero on the main thread shortly // after this function returns while some ipdl code still needs to run on // this thread. // We must keep the compositor parent alive untill the code handling message // reception is finished on this thread. mSelfRef = this; - MessageLoop::current()->PostTask(FROM_HERE, - NewRunnableMethod(this,&CompositorBridgeParent::DeferredDestroy)); + MessageLoop::current()->PostTask(NewRunnableMethod(this,&CompositorBridgeParent::DeferredDestroy)); } void CompositorBridgeParent::ScheduleRenderOnCompositorThread() { - CancelableTask *renderTask = NewRunnableMethod(this, &CompositorBridgeParent::ScheduleComposition); MOZ_ASSERT(CompositorLoop()); - CompositorLoop()->PostTask(FROM_HERE, renderTask); + CompositorLoop()->PostTask(NewRunnableMethod(this, &CompositorBridgeParent::ScheduleComposition)); } void CompositorBridgeParent::InvalidateOnCompositorThread() { - CancelableTask *renderTask = NewRunnableMethod(this, &CompositorBridgeParent::Invalidate); MOZ_ASSERT(CompositorLoop()); - CompositorLoop()->PostTask(FROM_HERE, renderTask); + CompositorLoop()->PostTask(NewRunnableMethod(this, &CompositorBridgeParent::Invalidate)); } void CompositorBridgeParent::PauseComposition() { MOZ_ASSERT(IsInCompositorThread(), "PauseComposition() can only be called on the compositor thread"); @@ -1083,64 +1082,58 @@ CompositorBridgeParent::ResumeCompositio * This will execute a pause synchronously, waiting to make sure that the compositor * really is paused. */ void CompositorBridgeParent::SchedulePauseOnCompositorThread() { MonitorAutoLock lock(mPauseCompositionMonitor); - CancelableTask *pauseTask = NewRunnableMethod(this, - &CompositorBridgeParent::PauseComposition); MOZ_ASSERT(CompositorLoop()); - CompositorLoop()->PostTask(FROM_HERE, pauseTask); + CompositorLoop()->PostTask(NewRunnableMethod(this, &CompositorBridgeParent::PauseComposition)); // Wait until the pause has actually been processed by the compositor thread lock.Wait(); } bool CompositorBridgeParent::ScheduleResumeOnCompositorThread() { MonitorAutoLock lock(mResumeCompositionMonitor); - CancelableTask *resumeTask = - NewRunnableMethod(this, &CompositorBridgeParent::ResumeComposition); MOZ_ASSERT(CompositorLoop()); - CompositorLoop()->PostTask(FROM_HERE, resumeTask); + CompositorLoop()->PostTask(NewRunnableMethod(this, &CompositorBridgeParent::ResumeComposition)); // Wait until the resume has actually been processed by the compositor thread lock.Wait(); return !mPaused; } bool CompositorBridgeParent::ScheduleResumeOnCompositorThread(int width, int height) { MonitorAutoLock lock(mResumeCompositionMonitor); - CancelableTask *resumeTask = - NewRunnableMethod(this, &CompositorBridgeParent::ResumeCompositionAndResize, width, height); MOZ_ASSERT(CompositorLoop()); - CompositorLoop()->PostTask(FROM_HERE, resumeTask); + CompositorLoop()->PostTask(NewRunnableMethod(this, &CompositorBridgeParent::ResumeCompositionAndResize, width, height)); // Wait until the resume has actually been processed by the compositor thread lock.Wait(); return !mPaused; } void -CompositorBridgeParent::ScheduleTask(CancelableTask* task, int time) +CompositorBridgeParent::ScheduleTask(already_AddRefed<CancelableRunnable> task, int time) { if (time == 0) { - MessageLoop::current()->PostTask(FROM_HERE, task); + MessageLoop::current()->PostTask(Move(task)); } else { - MessageLoop::current()->PostDelayedTask(FROM_HERE, task, time); + MessageLoop::current()->PostDelayedTask(Move(task), time); } } void CompositorBridgeParent::NotifyShadowTreeTransaction(uint64_t aId, bool aIsFirstPaint, bool aScheduleComposite, uint32_t aPaintSequenceNumber, bool aIsRepeatTransaction) { @@ -1367,18 +1360,19 @@ CompositorBridgeParent::ScheduleRotation MOZ_ASSERT(IsInCompositorThread()); if (!aIsFirstPaint && !mCompositionManager->IsFirstPaint() && mCompositionManager->RequiresReorientation(aTargetConfig.orientation())) { if (mForceCompositionTask != nullptr) { mForceCompositionTask->Cancel(); } - mForceCompositionTask = NewRunnableMethod(this, &CompositorBridgeParent::ForceComposition); - ScheduleTask(mForceCompositionTask, gfxPrefs::OrientationSyncMillis()); + RefPtr<CancelableRunnable> task = NewRunnableMethod(this, &CompositorBridgeParent::ForceComposition); + mForceCompositionTask = task; + ScheduleTask(task.forget(), gfxPrefs::OrientationSyncMillis()); } } void CompositorBridgeParent::ShadowLayersUpdated(LayerTransactionParent* aLayerTree, const uint64_t& aTransactionId, const TargetConfig& aTargetConfig, const InfallibleTArray<PluginWindowData>& aUnused, @@ -1523,48 +1517,51 @@ CompositorBridgeParent::FlushApzRepaints void CompositorBridgeParent::GetAPZTestData(const LayerTransactionParent* aLayerTree, APZTestData* aOutData) { MonitorAutoLock lock(*sIndirectLayerTreesLock); *aOutData = sIndirectLayerTrees[mRootLayerTreeID].mApzTestData; } -class NotifyAPZConfirmedTargetTask : public Task +class NotifyAPZConfirmedTargetTask : public Runnable { public: explicit NotifyAPZConfirmedTargetTask(const RefPtr<APZCTreeManager>& aAPZCTM, const uint64_t& aInputBlockId, const nsTArray<ScrollableLayerGuid>& aTargets) : mAPZCTM(aAPZCTM), mInputBlockId(aInputBlockId), mTargets(aTargets) { } - virtual void Run() override { + NS_IMETHOD Run() override { mAPZCTM->SetTargetAPZC(mInputBlockId, mTargets); + return NS_OK; } private: RefPtr<APZCTreeManager> mAPZCTM; uint64_t mInputBlockId; nsTArray<ScrollableLayerGuid> mTargets; }; void CompositorBridgeParent::SetConfirmedTargetAPZC(const LayerTransactionParent* aLayerTree, const uint64_t& aInputBlockId, const nsTArray<ScrollableLayerGuid>& aTargets) { if (!mApzcTreeManager) { return; } - APZThreadUtils::RunOnControllerThread(new NotifyAPZConfirmedTargetTask( - mApzcTreeManager, aInputBlockId, aTargets)); + RefPtr<Runnable> task = + new NotifyAPZConfirmedTargetTask(mApzcTreeManager, aInputBlockId, aTargets); + APZThreadUtils::RunOnControllerThread(task.forget()); + } void CompositorBridgeParent::InitializeLayerManager(const nsTArray<LayersBackend>& aBackendHints) { NS_ASSERTION(!mLayerManager, "Already initialised mLayerManager"); NS_ASSERTION(!mCompositor, "Already initialised mCompositor"); @@ -1771,18 +1768,17 @@ CompositorBridgeParent::DeallocateLayerT MOZ_ASSERT(NS_IsMainThread()); // Here main thread notifies compositor to remove an element from // sIndirectLayerTrees. This removed element might be queried soon. // Checking the elements of sIndirectLayerTrees exist or not before using. if (!CompositorLoop()) { gfxCriticalError() << "Attempting to post to a invalid Compositor Loop"; return; } - CompositorLoop()->PostTask(FROM_HERE, - NewRunnableFunction(&EraseLayerState, aId)); + CompositorLoop()->PostTask(NewRunnableFunction(&EraseLayerState, aId)); } /* static */ void CompositorBridgeParent::SwapLayerTreeObservers(uint64_t aLayerId, uint64_t aOtherLayerId) { EnsureLayerTreeMapReady(); MonitorAutoLock lock(*sIndirectLayerTreesLock); NS_ASSERTION(sIndirectLayerTrees.find(aLayerId) != sIndirectLayerTrees.end(), @@ -1822,18 +1818,17 @@ ScopedLayerTreeRegistration::~ScopedLaye } /*static*/ void CompositorBridgeParent::SetControllerForLayerTree(uint64_t aLayersId, GeckoContentController* aController) { // This ref is adopted by UpdateControllerForLayersId(). aController->AddRef(); - CompositorLoop()->PostTask(FROM_HERE, - NewRunnableFunction(&UpdateControllerForLayersId, + CompositorLoop()->PostTask(NewRunnableFunction(&UpdateControllerForLayersId, aLayersId, aController)); } /*static*/ APZCTreeManager* CompositorBridgeParent::GetAPZCTreeManager(uint64_t aLayersId) { EnsureLayerTreeMapReady(); @@ -1866,17 +1861,17 @@ InsertVsyncProfilerMarker(TimeStamp aVsy #endif } /*static */ void CompositorBridgeParent::PostInsertVsyncProfilerMarker(TimeStamp aVsyncTimestamp) { // Called in the vsync thread if (profiler_is_active() && sCompositorThreadHolder) { - CompositorLoop()->PostTask(FROM_HERE, + CompositorLoop()->PostTask( NewRunnableFunction(InsertVsyncProfilerMarker, aVsyncTimestamp)); } } /* static */ void CompositorBridgeParent::RequestNotifyLayerTreeReady(uint64_t aLayersId, CompositorUpdateObserver* aObserver) { EnsureLayerTreeMapReady(); @@ -2106,17 +2101,17 @@ CompositorBridgeParent::InvalidateRemote bool CompositorBridgeParent::ResetCompositor(const nsTArray<LayersBackend>& aBackendHints, TextureFactoryIdentifier* aOutIdentifier) { Maybe<TextureFactoryIdentifier> newIdentifier; { MonitorAutoLock lock(mResetCompositorMonitor); - CompositorLoop()->PostTask(FROM_HERE, + CompositorLoop()->PostTask( NewRunnableMethod(this, &CompositorBridgeParent::ResetCompositorTask, aBackendHints, &newIdentifier)); mResetCompositorMonitor.Wait(); } @@ -2216,17 +2211,16 @@ CompositorBridgeParent::Create(Transport if (aProcessHost) { cpcp->mSubprocess = aProcessHost; aProcessHost->AssociateActor(); } cpcp->mSelfRef = cpcp; CompositorLoop()->PostTask( - FROM_HERE, NewRunnableFunction(OpenCompositor, cpcp.get(), aTransport, aOtherPid, XRE_GetIOMessageLoop())); // The return value is just compared to null for success checking, // we're not sharing a ref. return cpcp.get(); } static void @@ -2279,17 +2273,17 @@ CrossProcessCompositorBridgeParent::Acto if (mSubprocess) { mSubprocess->DissociateActor(); mSubprocess = nullptr; } // We must keep this object alive untill the code handling message // reception is finished on this thread. - MessageLoop::current()->PostTask(FROM_HERE, + MessageLoop::current()->PostTask( NewRunnableMethod(this, &CrossProcessCompositorBridgeParent::DeferredDestroy)); } PLayerTransactionParent* CrossProcessCompositorBridgeParent::AllocPLayerTransactionParent( const nsTArray<LayersBackend>&, const uint64_t& aId, TextureFactoryIdentifier* aTextureFactoryIdentifier, @@ -2524,37 +2518,33 @@ CompositorBridgeParent::UpdatePluginWind mLastPluginUpdateLayerTreeId = aId; mCachedPluginData = lts.mPluginData; return true; } void CompositorBridgeParent::ScheduleShowAllPluginWindows() { - CancelableTask *pluginTask = - NewRunnableMethod(this, &CompositorBridgeParent::ShowAllPluginWindows); MOZ_ASSERT(CompositorLoop()); - CompositorLoop()->PostTask(FROM_HERE, pluginTask); + CompositorLoop()->PostTask(NewRunnableMethod(this, &CompositorBridgeParent::ShowAllPluginWindows)); } void CompositorBridgeParent::ShowAllPluginWindows() { MOZ_ASSERT(!NS_IsMainThread()); mDeferPluginWindows = false; ScheduleComposition(); } void CompositorBridgeParent::ScheduleHideAllPluginWindows() { - CancelableTask *pluginTask = - NewRunnableMethod(this, &CompositorBridgeParent::HideAllPluginWindows); MOZ_ASSERT(CompositorLoop()); - CompositorLoop()->PostTask(FROM_HERE, pluginTask); + CompositorLoop()->PostTask(NewRunnableMethod(this, &CompositorBridgeParent::HideAllPluginWindows)); } void CompositorBridgeParent::HideAllPluginWindows() { MOZ_ASSERT(!NS_IsMainThread()); // No plugins in the cache implies no plugins to manage // in this content. @@ -2737,18 +2727,18 @@ CrossProcessCompositorBridgeParent::Defe mCompositorThreadHolder = nullptr; mSelfRef = nullptr; } CrossProcessCompositorBridgeParent::~CrossProcessCompositorBridgeParent() { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(XRE_GetIOMessageLoop()); - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, - new DeleteTask<Transport>(mTransport)); + RefPtr<DeleteTask<Transport>> task = new DeleteTask<Transport>(mTransport); + XRE_GetIOMessageLoop()->PostTask(task.forget()); } IToplevelProtocol* CrossProcessCompositorBridgeParent::CloneToplevel( const InfallibleTArray<mozilla::ipc::ProtocolFdMapping>& aFds, base::ProcessHandle aPeerProcess, mozilla::ipc::ProtocolCloneContext* aCtx) {
--- a/gfx/layers/ipc/CompositorBridgeParent.h +++ b/gfx/layers/ipc/CompositorBridgeParent.h @@ -34,21 +34,23 @@ #include "mozilla/layers/PCompositorBridgeParent.h" #include "mozilla/layers/ShadowLayersManager.h" // for ShadowLayersManager #include "mozilla/layers/APZTestData.h" #include "nsAutoPtr.h" // for nsRefPtr #include "nsISupportsImpl.h" #include "ThreadSafeRefcountingWithMainThreadDestruction.h" #include "mozilla/VsyncDispatcher.h" -class CancelableTask; class MessageLoop; class nsIWidget; namespace mozilla { + +class CancelableRunnable; + namespace gfx { class DrawTarget; } // namespace gfx namespace ipc { class GeckoChildProcessHost; } // namespace ipc @@ -121,17 +123,17 @@ public: void SetDisplay(bool aDisplayEnable); #endif #endif bool NotifyVsync(TimeStamp aVsyncTimestamp); void SetNeedsComposite(); void OnForceComposeToTarget(); - void ScheduleTask(CancelableTask*, int); + void ScheduleTask(already_AddRefed<CancelableRunnable>, int); void ResumeComposition(); void ComposeToTarget(gfx::DrawTarget* aTarget, const gfx::IntRect* aRect = nullptr); void PostCompositeTask(TimeStamp aCompositeTimestamp); void Destroy(); void ScheduleComposition(); void CancelCurrentCompositeTask(); bool NeedsComposite(); void Composite(TimeStamp aVsyncTimestamp); @@ -188,26 +190,26 @@ private: bool mAsapScheduling; bool mIsObservingVsync; uint32_t mNeedsComposite; int32_t mVsyncNotificationsSkipped; RefPtr<CompositorVsyncDispatcher> mCompositorVsyncDispatcher; RefPtr<CompositorVsyncScheduler::Observer> mVsyncObserver; mozilla::Monitor mCurrentCompositeTaskMonitor; - CancelableTask* mCurrentCompositeTask; + RefPtr<CancelableRunnable> mCurrentCompositeTask; mozilla::Monitor mSetNeedsCompositeMonitor; - CancelableTask* mSetNeedsCompositeTask; + RefPtr<CancelableRunnable> mSetNeedsCompositeTask; #ifdef MOZ_WIDGET_GONK #if ANDROID_VERSION >= 19 bool mDisplayEnabled; mozilla::Monitor mSetDisplayMonitor; - CancelableTask* mSetDisplayTask; + RefPtr<CancelableRunnable> mSetDisplayTask; #endif #endif }; class CompositorUpdateObserver { public: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorUpdateObserver); @@ -519,17 +521,17 @@ protected: void DeferredDestroy(); virtual PLayerTransactionParent* AllocPLayerTransactionParent(const nsTArray<LayersBackend>& aBackendHints, const uint64_t& aId, TextureFactoryIdentifier* aTextureFactoryIdentifier, bool* aSuccess) override; virtual bool DeallocPLayerTransactionParent(PLayerTransactionParent* aLayers) override; - virtual void ScheduleTask(CancelableTask*, int); + virtual void ScheduleTask(already_AddRefed<CancelableRunnable>, int); void CompositeToTarget(gfx::DrawTarget* aTarget, const gfx::IntRect* aRect = nullptr); void SetEGLSurfaceSize(int width, int height); void InitializeLayerManager(const nsTArray<LayersBackend>& aBackendHints); void PauseComposition(); void ResumeComposition(); void ResumeCompositionAndResize(int width, int height); @@ -581,17 +583,17 @@ protected: mozilla::Monitor mPauseCompositionMonitor; mozilla::Monitor mResumeCompositionMonitor; mozilla::Monitor mResetCompositorMonitor; uint64_t mCompositorID; const uint64_t mRootLayerTreeID; bool mOverrideComposeReadiness; - CancelableTask* mForceCompositionTask; + RefPtr<CancelableRunnable> mForceCompositionTask; RefPtr<APZCTreeManager> mApzcTreeManager; RefPtr<CompositorThreadHolder> mCompositorThreadHolder; RefPtr<CompositorVsyncScheduler> mCompositorScheduler; // This makes sure the compositorParent is not destroyed before receiving // confirmation that the channel is closed. // mSelfRef is cleared in DeferredDestroy which is scheduled by ActorDestroy.
--- a/gfx/layers/ipc/ImageBridgeChild.cpp +++ b/gfx/layers/ipc/ImageBridgeChild.cpp @@ -9,17 +9,16 @@ #include "ImageContainer.h" // for ImageContainer #include "Layers.h" // for Layer, etc #include "ShadowLayers.h" // for ShadowLayerForwarder #include "base/message_loop.h" // for MessageLoop #include "base/platform_thread.h" // for PlatformThread #include "base/process.h" // for ProcessId #include "base/task.h" // for NewRunnableFunction, etc #include "base/thread.h" // for Thread -#include "base/tracked.h" // for FROM_HERE #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc #include "mozilla/Monitor.h" // for Monitor, MonitorAutoLock #include "mozilla/ReentrantMonitor.h" // for ReentrantMonitor, etc #include "mozilla/ipc/MessageChannel.h" // for MessageChannel, etc #include "mozilla/ipc/Transport.h" // for Transport #include "mozilla/gfx/Point.h" // for IntSize #include "mozilla/layers/AsyncCanvasRenderer.h" #include "mozilla/media/MediaSystemResourceManager.h" // for MediaSystemResourceManager @@ -349,18 +348,19 @@ ImageBridgeChild::ImageBridgeChild() SetMessageLoopToPostDestructionTo(MessageLoop::current()); mTxn = new CompositableTransaction(); } ImageBridgeChild::~ImageBridgeChild() { MOZ_ASSERT(NS_IsMainThread()); - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, - new DeleteTask<Transport>(GetTransport())); + RefPtr<DeleteTask<Transport>> task = new DeleteTask<Transport>(GetTransport()); + + XRE_GetIOMessageLoop()->PostTask(task.forget()); delete mTxn; } void ImageBridgeChild::MarkShutDown() { MOZ_ASSERT(!mShuttingDown); @@ -432,18 +432,17 @@ ConnectImageBridgeInChildProcess(Transpo { // Bind the IPC channel to the image bridge thread. sImageBridgeChildSingleton->Open(aTransport, aOtherPid, XRE_GetIOMessageLoop(), ipc::ChildSide); #ifdef MOZ_NUWA_PROCESS if (IsNuwaProcess()) { sImageBridgeChildThread - ->message_loop()->PostTask(FROM_HERE, - NewRunnableFunction(NuwaMarkCurrentThread, + ->message_loop()->PostTask(NewRunnableFunction(NuwaMarkCurrentThread, (void (*)(void *))nullptr, (void *)nullptr)); } #endif } static void ReleaseImageClientNow(ImageClient* aClient, PImageContainerChild* aChild) @@ -476,17 +475,16 @@ void ImageBridgeChild::DispatchReleaseIm MOZ_ASSERT(aClient->GetIPDLActor() == nullptr); aClient->Release(); } delete aChild; return; } sImageBridgeChildSingleton->GetMessageLoop()->PostTask( - FROM_HERE, NewRunnableFunction(&ReleaseImageClientNow, aClient, aChild)); } static void ReleaseCanvasClientNow(CanvasClient* aClient) { MOZ_ASSERT(InImageBridgeChildThread()); aClient->Release(); } @@ -505,17 +503,16 @@ void ImageBridgeChild::DispatchReleaseCa // has already shut down, along with the CompositableChild, which means no // message will be sent and it is safe to run this code from any thread. MOZ_ASSERT(aClient->GetIPDLActor() == nullptr); aClient->Release(); return; } sImageBridgeChildSingleton->GetMessageLoop()->PostTask( - FROM_HERE, NewRunnableFunction(&ReleaseCanvasClientNow, aClient)); } static void ReleaseTextureClientNow(TextureClient* aClient) { MOZ_ASSERT(InImageBridgeChildThread()); RELEASE_MANUALLY(aClient); } @@ -534,17 +531,16 @@ void ImageBridgeChild::DispatchReleaseTe // has already shut down, along with the TextureChild, which means no // message will be sent and it is safe to run this code from any thread. MOZ_ASSERT(aClient->GetIPDLActor() == nullptr); RELEASE_MANUALLY(aClient); return; } sImageBridgeChildSingleton->GetMessageLoop()->PostTask( - FROM_HERE, NewRunnableFunction(&ReleaseTextureClientNow, aClient)); } static void UpdateImageClientNow(ImageClient* aClient, RefPtr<ImageContainer>&& aContainer) { if (!ImageBridgeChild::IsCreated() || ImageBridgeChild::IsShutDown()) { NS_WARNING("Something is holding on to graphics resources after the shutdown" "of the graphics subsystem!"); @@ -570,17 +566,16 @@ void ImageBridgeChild::DispatchImageClie return; } if (InImageBridgeChildThread()) { UpdateImageClientNow(aClient, aContainer); return; } sImageBridgeChildSingleton->GetMessageLoop()->PostTask( - FROM_HERE, NewRunnableFunction(&UpdateImageClientNow, aClient, RefPtr<ImageContainer>(aContainer))); } static void UpdateAsyncCanvasRendererSync(AsyncCanvasRenderer* aWrapper, ReentrantMonitor* aBarrier, bool* const outDone) { ImageBridgeChild::UpdateAsyncCanvasRendererNow(aWrapper); @@ -600,17 +595,16 @@ void ImageBridgeChild::UpdateAsyncCanvas return; } ReentrantMonitor barrier("UpdateAsyncCanvasRenderer Lock"); ReentrantMonitorAutoEnter autoMon(barrier); bool done = false; sImageBridgeChildSingleton->GetMessageLoop()->PostTask( - FROM_HERE, NewRunnableFunction(&UpdateAsyncCanvasRendererSync, aWrapper, &barrier, &done)); // should stop the thread until the CanvasClient has been created on // the other thread while (!done) { barrier.Wait(); } } @@ -691,17 +685,16 @@ void ImageBridgeChild::FlushAllImages(Im RefPtr<AsyncTransactionWaiter> waiter; #ifdef MOZ_WIDGET_GONK waiter = new AsyncTransactionWaiter(); // This increment is balanced by the decrement in FlushAllImagesSync waiter->IncrementWaitCount(); #endif sImageBridgeChildSingleton->GetMessageLoop()->PostTask( - FROM_HERE, NewRunnableFunction(&FlushAllImagesSync, aClient, aContainer, waiter, &barrier, &done)); while (!done) { barrier.Wait(); } #ifdef MOZ_WIDGET_GONK waiter->WaitComplete(); @@ -785,21 +778,19 @@ ImageBridgeChild::StartUpInChildProcess( sImageBridgeChildThread = new ImageBridgeThread(); if (!sImageBridgeChildThread->Start()) { return nullptr; } sImageBridgeChildSingleton = new ImageBridgeChild(); sImageBridgeChildSingleton->GetMessageLoop()->PostTask( - FROM_HERE, NewRunnableFunction(ConnectImageBridgeInChildProcess, aTransport, aOtherPid)); sImageBridgeChildSingleton->GetMessageLoop()->PostTask( - FROM_HERE, NewRunnableFunction(CallSendImageBridgeThreadId, sImageBridgeChildSingleton.get())); return sImageBridgeChildSingleton; } void ImageBridgeChild::ShutDown() { @@ -810,29 +801,29 @@ void ImageBridgeChild::ShutDown() if (ImageBridgeChild::IsCreated()) { MOZ_ASSERT(!sImageBridgeChildSingleton->mShuttingDown); { ReentrantMonitor barrier("ImageBridge ShutdownStep1 lock"); ReentrantMonitorAutoEnter autoMon(barrier); bool done = false; - sImageBridgeChildSingleton->GetMessageLoop()->PostTask(FROM_HERE, + sImageBridgeChildSingleton->GetMessageLoop()->PostTask( NewRunnableFunction(&ImageBridgeShutdownStep1, &barrier, &done)); while (!done) { barrier.Wait(); } } { ReentrantMonitor barrier("ImageBridge ShutdownStep2 lock"); ReentrantMonitorAutoEnter autoMon(barrier); bool done = false; - sImageBridgeChildSingleton->GetMessageLoop()->PostTask(FROM_HERE, + sImageBridgeChildSingleton->GetMessageLoop()->PostTask( NewRunnableFunction(&ImageBridgeShutdownStep2, &barrier, &done)); while (!done) { barrier.Wait(); } } sImageBridgeChildSingleton = nullptr; @@ -849,17 +840,16 @@ bool ImageBridgeChild::StartUpOnThread(T if (!aThread->IsRunning()) { aThread->Start(); } sImageBridgeChildSingleton = new ImageBridgeChild(); sImageBridgeParentSingleton = new ImageBridgeParent( CompositorBridgeParent::CompositorLoop(), nullptr, base::GetCurrentProcId()); sImageBridgeChildSingleton->ConnectAsync(sImageBridgeParentSingleton); sImageBridgeChildSingleton->GetMessageLoop()->PostTask( - FROM_HERE, NewRunnableFunction(CallSendImageBridgeThreadId, sImageBridgeChildSingleton.get())); return true; } else { return false; } } @@ -871,18 +861,18 @@ bool InImageBridgeChildThread() MessageLoop * ImageBridgeChild::GetMessageLoop() const { return sImageBridgeChildThread ? sImageBridgeChildThread->message_loop() : nullptr; } void ImageBridgeChild::ConnectAsync(ImageBridgeParent* aParent) { - GetMessageLoop()->PostTask(FROM_HERE, NewRunnableFunction(&ConnectImageBridge, - this, aParent)); + GetMessageLoop()->PostTask(NewRunnableFunction(&ConnectImageBridge, + this, aParent)); } void ImageBridgeChild::IdentifyCompositorTextureHost(const TextureFactoryIdentifier& aIdentifier) { if (sImageBridgeChildSingleton) { sImageBridgeChildSingleton->IdentifyTextureHost(aIdentifier); } @@ -895,17 +885,17 @@ ImageBridgeChild::CreateImageClient(Comp if (InImageBridgeChildThread()) { return CreateImageClientNow(aType, aImageContainer); } ReentrantMonitor barrier("CreateImageClient Lock"); ReentrantMonitorAutoEnter autoMon(barrier); bool done = false; RefPtr<ImageClient> result = nullptr; - GetMessageLoop()->PostTask(FROM_HERE, + GetMessageLoop()->PostTask( NewRunnableFunction(&CreateImageClientSync, &result, &barrier, aType, aImageContainer, &done)); // should stop the thread until the ImageClient has been created on // the other thread while (!done) { barrier.Wait(); } return result.forget(); @@ -935,18 +925,17 @@ ImageBridgeChild::CreateCanvasClient(Can if (InImageBridgeChildThread()) { return CreateCanvasClientNow(aType, aFlag); } ReentrantMonitor barrier("CreateCanvasClient Lock"); ReentrantMonitorAutoEnter autoMon(barrier); bool done = false; RefPtr<CanvasClient> result = nullptr; - GetMessageLoop()->PostTask(FROM_HERE, - NewRunnableFunction(&CreateCanvasClientSync, + GetMessageLoop()->PostTask(NewRunnableFunction(&CreateCanvasClientSync, &barrier, aType, aFlag, &result, &done)); // should stop the thread until the CanvasClient has been created on the // other thread while (!done) { barrier.Wait(); } return result.forget(); } @@ -1035,18 +1024,17 @@ ImageBridgeChild::DispatchAllocShmemInte ReentrantMonitor barrier("AllocatorProxy alloc"); ReentrantMonitorAutoEnter autoMon(barrier); AllocShmemParams params = { this, aSize, aType, aShmem, aUnsafe, true }; bool done = false; - GetMessageLoop()->PostTask(FROM_HERE, - NewRunnableFunction(&ProxyAllocShmemNow, + GetMessageLoop()->PostTask(NewRunnableFunction(&ProxyAllocShmemNow, ¶ms, &barrier, &done)); while (!done) { barrier.Wait(); } return params.mSuccess; } @@ -1072,18 +1060,17 @@ ImageBridgeChild::DeallocShmem(ipc::Shme { if (InImageBridgeChildThread()) { PImageBridgeChild::DeallocShmem(aShmem); } else { ReentrantMonitor barrier("AllocatorProxy Dealloc"); ReentrantMonitorAutoEnter autoMon(barrier); bool done = false; - GetMessageLoop()->PostTask(FROM_HERE, - NewRunnableFunction(&ProxyDeallocShmemNow, + GetMessageLoop()->PostTask(NewRunnableFunction(&ProxyDeallocShmemNow, this, &aShmem, &barrier, &done)); while (!done) { barrier.Wait(); } }
--- a/gfx/layers/ipc/ImageBridgeParent.cpp +++ b/gfx/layers/ipc/ImageBridgeParent.cpp @@ -5,17 +5,16 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ImageBridgeParent.h" #include <stdint.h> // for uint64_t, uint32_t #include "CompositableHost.h" // for CompositableParent, Create #include "base/message_loop.h" // for MessageLoop #include "base/process.h" // for ProcessId #include "base/task.h" // for CancelableTask, DeleteTask, etc -#include "base/tracked.h" // for FROM_HERE #include "mozilla/gfx/Point.h" // for IntSize #include "mozilla/Hal.h" // for hal::SetCurrentThreadPriority() #include "mozilla/HalTypes.h" // for hal::THREAD_PRIORITY_COMPOSITOR #include "mozilla/ipc/MessageChannel.h" // for MessageChannel, etc #include "mozilla/ipc/ProtocolUtils.h" #include "mozilla/ipc/Transport.h" // for Transport #include "mozilla/ipc/GeckoChildProcessHost.h" #include "mozilla/media/MediaSystemResourceManagerParent.h" // for MediaSystemResourceManagerParent @@ -78,18 +77,18 @@ ImageBridgeParent::ImageBridgeParent(Mes } ImageBridgeParent::~ImageBridgeParent() { MOZ_ASSERT(NS_IsMainThread()); if (mTransport) { MOZ_ASSERT(XRE_GetIOMessageLoop()); - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, - new DeleteTask<Transport>(mTransport)); + RefPtr<DeleteTask<Transport>> task(new DeleteTask<Transport>(mTransport)); + XRE_GetIOMessageLoop()->PostTask(task.forget()); } nsTArray<PImageContainerParent*> parents; ManagedPImageContainerParent(parents); for (PImageContainerParent* p : parents) { delete p; } @@ -103,17 +102,16 @@ ImageBridgeParent::ActorDestroy(ActorDes mClosed = true; if (mSubprocess) { mSubprocess->DissociateActor(); mSubprocess = nullptr; } MessageLoop::current()->PostTask( - FROM_HERE, NewRunnableMethod(this, &ImageBridgeParent::DeferredDestroy)); // It is very important that this method gets called at shutdown (be it a clean // or an abnormal shutdown), because DeferredDestroy is what clears mSelfRef. // If mSelfRef is not null and ActorDestroy is not called, the ImageBridgeParent // is leaked which causes the CompositorThreadHolder to be leaked and // CompsoitorParent's shutdown ends up spinning the event loop forever, waiting // for the compositor thread to terminate. @@ -206,18 +204,17 @@ ImageBridgeParent::Create(Transport* aTr MessageLoop* loop = CompositorBridgeParent::CompositorLoop(); RefPtr<ImageBridgeParent> bridge = new ImageBridgeParent(loop, aTransport, aChildProcessId); if (aProcessHost) { bridge->mSubprocess = aProcessHost; aProcessHost->AssociateActor(); } - loop->PostTask(FROM_HERE, - NewRunnableFunction(ConnectImageBridgeInParentProcess, + loop->PostTask(NewRunnableFunction(ConnectImageBridgeInParentProcess, bridge.get(), aTransport, aChildProcessId)); return bridge.get(); } bool ImageBridgeParent::RecvWillClose() { // If there is any texture still alive we have to force it to deallocate the // device data (GL textures, etc.) now because shortly after SenStop() returns
--- a/gfx/layers/ipc/RemoteContentController.cpp +++ b/gfx/layers/ipc/RemoteContentController.cpp @@ -54,17 +54,16 @@ void RemoteContentController::HandleDoubleTap(const CSSPoint& aPoint, Modifiers aModifiers, const ScrollableLayerGuid& aGuid) { if (MessageLoop::current() != mUILoop) { // We have to send this message from the "UI thread" (main // thread). mUILoop->PostTask( - FROM_HERE, NewRunnableMethod(this, &RemoteContentController::HandleDoubleTap, aPoint, aModifiers, aGuid)); return; } if (CanSend()) { Unused << SendHandleDoubleTap(mBrowserParent->AdjustTapToChildWidget(aPoint), aModifiers, aGuid); } @@ -74,17 +73,16 @@ void RemoteContentController::HandleSingleTap(const CSSPoint& aPoint, Modifiers aModifiers, const ScrollableLayerGuid& aGuid) { if (MessageLoop::current() != mUILoop) { // We have to send this message from the "UI thread" (main // thread). mUILoop->PostTask( - FROM_HERE, NewRunnableMethod(this, &RemoteContentController::HandleSingleTap, aPoint, aModifiers, aGuid)); return; } bool callTakeFocusForClickFromTap; layout::RenderFrameParent* frame; if (mBrowserParent && (frame = mBrowserParent->GetRenderFrame()) && @@ -108,35 +106,34 @@ RemoteContentController::HandleLongTap(c Modifiers aModifiers, const ScrollableLayerGuid& aGuid, uint64_t aInputBlockId) { if (MessageLoop::current() != mUILoop) { // We have to send this message from the "UI thread" (main // thread). mUILoop->PostTask( - FROM_HERE, NewRunnableMethod(this, &RemoteContentController::HandleLongTap, aPoint, aModifiers, aGuid, aInputBlockId)); return; } if (CanSend()) { Unused << SendHandleLongTap(mBrowserParent->AdjustTapToChildWidget(aPoint), aModifiers, aGuid, aInputBlockId); } } void -RemoteContentController::PostDelayedTask(Task* aTask, int aDelayMs) +RemoteContentController::PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs) { #ifdef MOZ_ANDROID_APZ - AndroidBridge::Bridge()->PostTaskToUiThread(aTask, aDelayMs); + AndroidBridge::Bridge()->PostTaskToUiThread(Move(aTask), aDelayMs); #else (MessageLoop::current() ? MessageLoop::current() : mUILoop)-> - PostDelayedTask(FROM_HERE, aTask, aDelayMs); + PostDelayedTask(Move(aTask), aDelayMs); #endif } bool RemoteContentController::GetTouchSensitiveRegion(CSSRect* aOutRegion) { MutexAutoLock lock(mMutex); if (mTouchSensitiveRegion.IsEmpty()) { @@ -149,33 +146,31 @@ RemoteContentController::GetTouchSensiti void RemoteContentController::NotifyAPZStateChange(const ScrollableLayerGuid& aGuid, APZStateChange aChange, int aArg) { if (MessageLoop::current() != mUILoop) { mUILoop->PostTask( - FROM_HERE, NewRunnableMethod(this, &RemoteContentController::NotifyAPZStateChange, aGuid, aChange, aArg)); return; } if (CanSend()) { Unused << SendNotifyAPZStateChange(aGuid.mScrollId, aChange, aArg); } } void RemoteContentController::NotifyMozMouseScrollEvent(const FrameMetrics::ViewID& aScrollId, const nsString& aEvent) { if (MessageLoop::current() != mUILoop) { mUILoop->PostTask( - FROM_HERE, NewRunnableMethod(this, &RemoteContentController::NotifyMozMouseScrollEvent, aScrollId, aEvent)); return; } if (mBrowserParent) { Unused << mBrowserParent->SendMouseScrollTestEvent(mLayersId, aScrollId, aEvent); }
--- a/gfx/layers/ipc/RemoteContentController.h +++ b/gfx/layers/ipc/RemoteContentController.h @@ -50,17 +50,17 @@ public: Modifiers aModifiers, const ScrollableLayerGuid& aGuid) override; virtual void HandleLongTap(const CSSPoint& aPoint, Modifiers aModifiers, const ScrollableLayerGuid& aGuid, uint64_t aInputBlockId) override; - virtual void PostDelayedTask(Task* aTask, int aDelayMs) override; + virtual void PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs) override; virtual bool GetTouchSensitiveRegion(CSSRect* aOutRegion) override; virtual void NotifyAPZStateChange(const ScrollableLayerGuid& aGuid, APZStateChange aChange, int aArg) override; virtual void NotifyMozMouseScrollEvent(const FrameMetrics::ViewID& aScrollId,
--- a/gfx/layers/ipc/SharedBufferManagerChild.cpp +++ b/gfx/layers/ipc/SharedBufferManagerChild.cpp @@ -2,17 +2,16 @@ * vim: sw=2 ts=8 et : */ /* 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 "base/task.h" // for NewRunnableFunction, etc #include "base/thread.h" // for Thread -#include "base/tracked.h" // for FROM_HERE #include "mozilla/gfx/Logging.h" // for gfxDebug #include "mozilla/layers/SharedBufferManagerChild.h" #include "mozilla/layers/SharedBufferManagerParent.h" #include "mozilla/StaticPtr.h" // for StaticRefPtr #include "mozilla/ReentrantMonitor.h" // for ReentrantMonitor, etc #include "nsThreadUtils.h" // fo NS_IsMainThread #ifdef MOZ_NUWA_PROCESS @@ -102,18 +101,17 @@ ConnectSharedBufferManagerInChildProcess SharedBufferManagerChild::sSharedBufferManagerChildSingleton->Open(aTransport, aOtherPid, XRE_GetIOMessageLoop(), ipc::ChildSide); #ifdef MOZ_NUWA_PROCESS if (IsNuwaProcess()) { SharedBufferManagerChild::sSharedBufferManagerChildThread - ->message_loop()->PostTask(FROM_HERE, - NewRunnableFunction(NuwaMarkCurrentThread, + ->message_loop()->PostTask(NewRunnableFunction(NuwaMarkCurrentThread, (void (*)(void *))nullptr, (void *)nullptr)); } #endif } PSharedBufferManagerChild* SharedBufferManagerChild::StartUpInChildProcess(Transport* aTransport, @@ -123,17 +121,16 @@ SharedBufferManagerChild::StartUpInChild sSharedBufferManagerChildThread = new base::Thread("BufferMgrChild"); if (!sSharedBufferManagerChildThread->Start()) { return nullptr; } sSharedBufferManagerChildSingleton = new SharedBufferManagerChild(); sSharedBufferManagerChildSingleton->GetMessageLoop()->PostTask( - FROM_HERE, NewRunnableFunction(ConnectSharedBufferManagerInChildProcess, aTransport, aOtherPid)); return sSharedBufferManagerChildSingleton; } void SharedBufferManagerChild::ShutDown() @@ -178,17 +175,17 @@ SharedBufferManagerChild::DestroyManager if (!IsCreated()) { return; } ReentrantMonitor barrier("BufferManagerDestroyTask lock"); ReentrantMonitorAutoEnter autoMon(barrier); bool done = false; - sSharedBufferManagerChildSingleton->GetMessageLoop()->PostTask(FROM_HERE, + sSharedBufferManagerChildSingleton->GetMessageLoop()->PostTask( NewRunnableFunction(&DeleteSharedBufferManagerSync, &barrier, &done)); while (!done) { barrier.Wait(); } } MessageLoop * @@ -197,18 +194,18 @@ SharedBufferManagerChild::GetMessageLoop return sSharedBufferManagerChildThread != nullptr ? sSharedBufferManagerChildThread->message_loop() : nullptr; } void SharedBufferManagerChild::ConnectAsync(SharedBufferManagerParent* aParent) { - GetMessageLoop()->PostTask(FROM_HERE, NewRunnableFunction(&ConnectSharedBufferManager, - this, aParent)); + GetMessageLoop()->PostTask(NewRunnableFunction(&ConnectSharedBufferManager, + this, aParent)); } // dispatched function void SharedBufferManagerChild::AllocGrallocBufferSync(const GrallocParam& aParam, Monitor* aBarrier, bool* aDone) { @@ -245,17 +242,16 @@ SharedBufferManagerChild::AllocGrallocBu return SharedBufferManagerChild::AllocGrallocBufferNow(aSize, aFormat, aUsage, aBuffer); } Monitor barrier("AllocSurfaceDescriptorGralloc Lock"); MonitorAutoLock autoMon(barrier); bool done = false; GetMessageLoop()->PostTask( - FROM_HERE, NewRunnableFunction(&AllocGrallocBufferSync, GrallocParam(aSize, aFormat, aUsage, aBuffer), &barrier, &done)); while (!done) { barrier.Wait(); } return true; } @@ -300,18 +296,17 @@ SharedBufferManagerChild::DeallocGralloc return; } #endif if (InSharedBufferManagerChildThread()) { return SharedBufferManagerChild::DeallocGrallocBufferNow(aBuffer); } - GetMessageLoop()->PostTask(FROM_HERE, NewRunnableFunction(&DeallocGrallocBufferSync, - aBuffer)); + GetMessageLoop()->PostTask(NewRunnableFunction(&DeallocGrallocBufferSync, aBuffer)); } void SharedBufferManagerChild::DeallocGrallocBufferNow(const mozilla::layers::MaybeMagicGrallocBufferHandle& aBuffer) { #ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC NS_ASSERTION(aBuffer.type() != mozilla::layers::MaybeMagicGrallocBufferHandle::TMagicGrallocBufferHandle, "We shouldn't try to do IPC with real buffer");
--- a/gfx/layers/ipc/SharedBufferManagerParent.cpp +++ b/gfx/layers/ipc/SharedBufferManagerParent.cpp @@ -3,17 +3,16 @@ /* 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 "mozilla/layers/SharedBufferManagerParent.h" #include "base/message_loop.h" // for MessageLoop #include "base/process.h" // for ProcessId #include "base/task.h" // for CancelableTask, DeleteTask, etc -#include "base/tracked.h" // for FROM_HERE #include "base/thread.h" #include "mozilla/ipc/MessageChannel.h" // for MessageChannel, etc #include "mozilla/ipc/ProtocolUtils.h" #include "mozilla/ipc/Transport.h" // for Transport #include "mozilla/UniquePtr.h" // for UniquePtr #include "mozilla/unused.h" #include "nsIMemoryReporter.h" #ifdef MOZ_WIDGET_GONK @@ -110,23 +109,23 @@ void InitGralloc() { #ifdef MOZ_WIDGET_GONK RegisterStrongMemoryReporter(new GrallocReporter()); #endif } /** * Task that deletes SharedBufferManagerParent on a specified thread. */ -class DeleteSharedBufferManagerParentTask : public Task +class DeleteSharedBufferManagerParentTask : public Runnable { public: explicit DeleteSharedBufferManagerParentTask(UniquePtr<SharedBufferManagerParent> aSharedBufferManager) : mSharedBufferManager(Move(aSharedBufferManager)) { } - virtual void Run() override {} + NS_IMETHOD Run() override { return NS_OK; } private: UniquePtr<SharedBufferManagerParent> mSharedBufferManager; }; SharedBufferManagerParent::SharedBufferManagerParent(Transport* aTransport, base::ProcessId aOwner, base::Thread* aThread) : mTransport(aTransport) , mThread(aThread) , mMainMessageLoop(MessageLoop::current()) @@ -150,34 +149,34 @@ SharedBufferManagerParent::SharedBufferM mOwner = aOwner; sManagers[aOwner] = this; } SharedBufferManagerParent::~SharedBufferManagerParent() { MonitorAutoLock lock(*sManagerMonitor.get()); if (mTransport) { - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, - new DeleteTask<Transport>(mTransport)); + RefPtr<DeleteTask<Transport>> task = new DeleteTask<Transport>(mTransport); + XRE_GetIOMessageLoop()->PostTask(task.forget()); } sManagers.erase(mOwner); delete mThread; } void SharedBufferManagerParent::ActorDestroy(ActorDestroyReason aWhy) { MutexAutoLock lock(mLock); mDestroyed = true; #ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC mBuffers.clear(); #endif - DeleteSharedBufferManagerParentTask* task = + RefPtr<DeleteSharedBufferManagerParentTask> task = new DeleteSharedBufferManagerParentTask(UniquePtr<SharedBufferManagerParent>(this)); - mMainMessageLoop->PostTask(FROM_HERE, task); + mMainMessageLoop->PostTask(task.forget()); } static void ConnectSharedBufferManagerInParentProcess(SharedBufferManagerParent* aManager, Transport* aTransport, base::ProcessId aOtherPid) { aManager->Open(aTransport, aOtherPid, XRE_GetIOMessageLoop(), ipc::ParentSide); @@ -190,18 +189,17 @@ PSharedBufferManagerParent* SharedBuffer char thrname[128]; base::snprintf(thrname, 128, "BufMgrParent#%d", aOtherPid); thread = new base::Thread(thrname); SharedBufferManagerParent* manager = new SharedBufferManagerParent(aTransport, aOtherPid, thread); if (!thread->IsRunning()) { thread->Start(); } - thread->message_loop()->PostTask(FROM_HERE, - NewRunnableFunction(ConnectSharedBufferManagerInParentProcess, + thread->message_loop()->PostTask(NewRunnableFunction(ConnectSharedBufferManagerInParentProcess, manager, aTransport, aOtherPid)); return manager; } bool SharedBufferManagerParent::RecvAllocateGrallocBuffer(const IntSize& aSize, const uint32_t& aFormat, const uint32_t& aUsage, mozilla::layers::MaybeMagicGrallocBufferHandle* aHandle) { #ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC @@ -292,17 +290,17 @@ void SharedBufferManagerParent::DropGral MutexAutoLock mgrlock(mgr->mLock); if (mgr->mDestroyed) { return; } if (PlatformThread::CurrentId() == mgr->mThread->thread_id()) { MOZ_CRASH("GFX: SharedBufferManagerParent::DropGrallocBuffer should not be called on SharedBufferManagerParent thread"); } else { - mgr->mThread->message_loop()->PostTask(FROM_HERE, + mgr->mThread->message_loop()->PostTask( NewRunnableFunction(&DropGrallocBufferSync, mgr, aDesc)); } return; } void SharedBufferManagerParent::DropGrallocBufferImpl(mozilla::layers::SurfaceDescriptor aDesc) { MutexAutoLock lock(mLock);
--- a/gfx/thebes/SoftwareVsyncSource.cpp +++ b/gfx/thebes/SoftwareVsyncSource.cpp @@ -18,18 +18,17 @@ SoftwareVsyncSource::SoftwareVsyncSource SoftwareVsyncSource::~SoftwareVsyncSource() { MOZ_ASSERT(NS_IsMainThread()); mGlobalDisplay->Shutdown(); mGlobalDisplay = nullptr; } SoftwareDisplay::SoftwareDisplay() - : mCurrentVsyncTask(nullptr) - , mVsyncEnabled(false) + : mVsyncEnabled(false) { // Mimic 60 fps MOZ_ASSERT(NS_IsMainThread()); const double rate = 1000.0 / (double) gfxPlatform::GetSoftwareVsyncRate(); mVsyncRate = mozilla::TimeDuration::FromMilliseconds(rate); mVsyncThread = new base::Thread("SoftwareVsyncThread"); MOZ_RELEASE_ASSERT(mVsyncThread->Start(), "Could not start software vsync thread"); } @@ -41,17 +40,17 @@ SoftwareDisplay::EnableVsync() { MOZ_ASSERT(mVsyncThread->IsRunning()); if (NS_IsMainThread()) { if (mVsyncEnabled) { return; } mVsyncEnabled = true; - mVsyncThread->message_loop()->PostTask(FROM_HERE, + mVsyncThread->message_loop()->PostTask( NewRunnableMethod(this, &SoftwareDisplay::EnableVsync)); return; } MOZ_ASSERT(IsInSoftwareVsyncThread()); NotifyVsync(mozilla::TimeStamp::Now()); } @@ -60,17 +59,17 @@ SoftwareDisplay::DisableVsync() { MOZ_ASSERT(mVsyncThread->IsRunning()); if (NS_IsMainThread()) { if (!mVsyncEnabled) { return; } mVsyncEnabled = false; - mVsyncThread->message_loop()->PostTask(FROM_HERE, + mVsyncThread->message_loop()->PostTask( NewRunnableMethod(this, &SoftwareDisplay::DisableVsync)); return; } MOZ_ASSERT(IsInSoftwareVsyncThread()); if (mCurrentVsyncTask) { mCurrentVsyncTask->Cancel(); mCurrentVsyncTask = nullptr; @@ -128,18 +127,19 @@ SoftwareDisplay::ScheduleNextVsync(mozil delay = mozilla::TimeDuration::FromMilliseconds(0); nextVsync = mozilla::TimeStamp::Now(); } mCurrentVsyncTask = NewRunnableMethod(this, &SoftwareDisplay::NotifyVsync, nextVsync); - mVsyncThread->message_loop()->PostDelayedTask(FROM_HERE, - mCurrentVsyncTask, + RefPtr<mozilla::CancelableRunnable> addrefedTask = mCurrentVsyncTask; + mVsyncThread->message_loop()->PostDelayedTask( + addrefedTask.forget(), delay.ToMilliseconds()); } void SoftwareDisplay::Shutdown() { MOZ_ASSERT(NS_IsMainThread()); DisableVsync();
--- a/gfx/thebes/SoftwareVsyncSource.h +++ b/gfx/thebes/SoftwareVsyncSource.h @@ -9,18 +9,16 @@ #include "mozilla/Monitor.h" #include "mozilla/RefPtr.h" #include "mozilla/TimeStamp.h" #include "base/thread.h" #include "nsISupportsImpl.h" #include "VsyncSource.h" -class CancelableTask; - class SoftwareDisplay final : public mozilla::gfx::VsyncSource::Display { NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SoftwareDisplay) public: SoftwareDisplay(); virtual void EnableVsync() override; virtual void DisableVsync() override; @@ -33,17 +31,17 @@ public: protected: ~SoftwareDisplay(); private: mozilla::TimeDuration mVsyncRate; // Use a chromium thread because nsITimers* fire on the main thread base::Thread* mVsyncThread; - CancelableTask* mCurrentVsyncTask; // only access on vsync thread + RefPtr<mozilla::CancelableRunnable> mCurrentVsyncTask; // only access on vsync thread bool mVsyncEnabled; // Only access on main thread }; // SoftwareDisplay // Fallback option to use a software timer to mimic vsync. Useful for gtests // To mimic a hardware vsync thread, we create a dedicated software timer // vsync thread. class SoftwareVsyncSource : public mozilla::gfx::VsyncSource {
--- a/gfx/thebes/gfxWindowsPlatform.cpp +++ b/gfx/thebes/gfxWindowsPlatform.cpp @@ -2665,19 +2665,18 @@ public: { // scope lock MonitorAutoLock lock(mVsyncEnabledLock); if (mVsyncEnabled) { return; } mVsyncEnabled = true; } - CancelableTask* vsyncStart = NewRunnableMethod(this, - &D3DVsyncDisplay::VBlankLoop); - mVsyncThread->message_loop()->PostTask(FROM_HERE, vsyncStart); + mVsyncThread->message_loop()->PostTask( + NewRunnableMethod(this, &D3DVsyncDisplay::VBlankLoop)); } virtual void DisableVsync() override { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(mVsyncThread->IsRunning()); MonitorAutoLock lock(mVsyncEnabledLock); if (!mVsyncEnabled) { @@ -2704,17 +2703,17 @@ public: NS_WARNING("DwmComposition dynamically disabled, falling back to software timers"); TimeStamp nextVsync = aVsyncTimestamp + mSoftwareVsyncRate; TimeDuration delay = nextVsync - TimeStamp::Now(); if (delay.ToMilliseconds() < 0) { delay = mozilla::TimeDuration::FromMilliseconds(0); } - mVsyncThread->message_loop()->PostDelayedTask(FROM_HERE, + mVsyncThread->message_loop()->PostDelayedTask( NewRunnableMethod(this, &D3DVsyncDisplay::VBlankLoop), delay.ToMilliseconds()); } TimeStamp GetAdjustedVsyncTimeStamp(LARGE_INTEGER& aFrequency, QPC_TIME& aQpcVblankTime) { TimeStamp vsync = TimeStamp::Now();
--- a/gfx/vr/ipc/VRManagerChild.cpp +++ b/gfx/vr/ipc/VRManagerChild.cpp @@ -33,18 +33,18 @@ VRManagerChild::VRManagerChild() VRManagerChild::~VRManagerChild() { MOZ_ASSERT(NS_IsMainThread()); MOZ_COUNT_DTOR(VRManagerChild); Transport* trans = GetTransport(); if (trans) { MOZ_ASSERT(XRE_GetIOMessageLoop()); - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, - new DeleteTask<Transport>(trans)); + RefPtr<DeleteTask<Transport>> task = new DeleteTask<Transport>(trans); + XRE_GetIOMessageLoop()->PostTask(task.forget()); } } /*static*/ VRManagerChild* VRManagerChild::Get() { MOZ_ASSERT(sVRManagerChildSingleton); return sVRManagerChildSingleton; @@ -104,17 +104,17 @@ VRManagerChild::Destroy() // This must not be called from the destructor! MOZ_ASSERT(mRefCnt != 0); // Keep ourselves alive until everything has been shut down RefPtr<VRManagerChild> selfRef = this; // The DeferredDestroyVRManager task takes ownership of // the VRManagerChild and will release it when it runs. - MessageLoop::current()->PostTask(FROM_HERE, + MessageLoop::current()->PostTask( NewRunnableFunction(DeferredDestroy, selfRef)); } bool VRManagerChild::RecvUpdateDeviceInfo(nsTArray<VRDeviceUpdate>&& aDeviceUpdates) { // mDevices could be a hashed container for more scalability, but not worth // it now as we expect < 10 entries.
--- a/gfx/vr/ipc/VRManagerParent.cpp +++ b/gfx/vr/ipc/VRManagerParent.cpp @@ -39,18 +39,18 @@ VRManagerParent::~VRManagerParent() { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(!mVRManagerHolder); Transport* trans = GetTransport(); if (trans) { MOZ_ASSERT(XRE_GetIOMessageLoop()); - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, - new DeleteTask<Transport>(trans)); + RefPtr<DeleteTask<Transport>> task = new DeleteTask<Transport>(trans); + XRE_GetIOMessageLoop()->PostTask(task.forget()); } MOZ_COUNT_DTOR(VRManagerParent); } void VRManagerParent::RegisterWithManager() { VRManager* vm = VRManager::Get(); vm->AddVRManagerParent(this); @@ -74,18 +74,17 @@ VRManagerParent::ConnectVRManagerInParen } /*static*/ VRManagerParent* VRManagerParent::CreateCrossProcess(Transport* aTransport, ProcessId aChildProcessId) { MessageLoop* loop = mozilla::layers::CompositorBridgeParent::CompositorLoop(); RefPtr<VRManagerParent> vmp = new VRManagerParent(loop, aTransport, aChildProcessId); vmp->mSelfRef = vmp; - loop->PostTask(FROM_HERE, - NewRunnableFunction(ConnectVRManagerInParentProcess, + loop->PostTask(NewRunnableFunction(ConnectVRManagerInParentProcess, vmp.get(), aTransport, aChildProcessId)); return vmp.get(); } /*static*/ void VRManagerParent::RegisterVRManagerInCompositorThread(VRManagerParent* aVRManager) { aVRManager->RegisterWithManager(); @@ -93,34 +92,32 @@ VRManagerParent::RegisterVRManagerInComp /*static*/ VRManagerParent* VRManagerParent::CreateSameProcess() { MessageLoop* loop = mozilla::layers::CompositorBridgeParent::CompositorLoop(); RefPtr<VRManagerParent> vmp = new VRManagerParent(loop, nullptr, base::GetCurrentProcId()); vmp->mCompositorThreadHolder = layers::GetCompositorThreadHolder(); vmp->mSelfRef = vmp; - loop->PostTask(FROM_HERE, - NewRunnableFunction(RegisterVRManagerInCompositorThread, vmp.get())); + loop->PostTask(NewRunnableFunction(RegisterVRManagerInCompositorThread, vmp.get())); return vmp.get(); } void VRManagerParent::DeferredDestroy() { mCompositorThreadHolder = nullptr; mSelfRef = nullptr; } void VRManagerParent::ActorDestroy(ActorDestroyReason why) { UnregisterFromManager(); MessageLoop::current()->PostTask( - FROM_HERE, NewRunnableMethod(this, &VRManagerParent::DeferredDestroy)); } mozilla::ipc::IToplevelProtocol* VRManagerParent::CloneToplevel(const InfallibleTArray<mozilla::ipc::ProtocolFdMapping>& aFds, base::ProcessHandle aPeerProcess, mozilla::ipc::ProtocolCloneContext* aCtx) {
--- a/ipc/chromium/moz.build +++ b/ipc/chromium/moz.build @@ -21,18 +21,16 @@ UNIFIED_SOURCES += [ 'src/base/pickle.cc', 'src/base/rand_util.cc', 'src/base/revocable_store.cc', 'src/base/string_piece.cc', 'src/base/string_util.cc', 'src/base/thread.cc', 'src/base/time.cc', 'src/base/timer.cc', - 'src/base/tracked.cc', - 'src/base/tracked_objects.cc', 'src/chrome/common/child_process.cc', 'src/chrome/common/child_process_host.cc', 'src/chrome/common/child_process_info.cc', 'src/chrome/common/child_thread.cc', 'src/chrome/common/chrome_switches.cc', 'src/chrome/common/ipc_channel.cc', 'src/chrome/common/ipc_message.cc', 'src/chrome/common/notification_service.cc',
--- a/ipc/chromium/src/base/message_loop.cc +++ b/ipc/chromium/src/base/message_loop.cc @@ -36,16 +36,19 @@ #endif #include "MessagePump.h" using base::Time; using base::TimeDelta; using base::TimeTicks; +using mozilla::Move; +using mozilla::Runnable; + static base::ThreadLocalPointer<MessageLoop>& get_tls_ptr() { static base::ThreadLocalPointer<MessageLoop> tls_ptr; return tls_ptr; } //------------------------------------------------------------------------------ // Logical events for Histogram profiling. Run with -message-loop-histogrammer @@ -235,86 +238,68 @@ void MessageLoop::RunInternal() { bool MessageLoop::ProcessNextDelayedNonNestableTask() { if (state_->run_depth > run_depth_base_) return false; if (deferred_non_nestable_work_queue_.empty()) return false; - Task* task = deferred_non_nestable_work_queue_.front().task; + RefPtr<Runnable> task = deferred_non_nestable_work_queue_.front().task.forget(); deferred_non_nestable_work_queue_.pop(); - RunTask(task); + RunTask(task.forget()); return true; } //------------------------------------------------------------------------------ void MessageLoop::Quit() { DCHECK(current() == this); if (state_) { state_->quit_received = true; } else { NOTREACHED() << "Must be inside Run to call Quit"; } } -void MessageLoop::PostTask( - const tracked_objects::Location& from_here, Task* task) { - PostTask_Helper(from_here, task, 0); -} - -void MessageLoop::PostDelayedTask( - const tracked_objects::Location& from_here, Task* task, int delay_ms) { - PostTask_Helper(from_here, task, delay_ms); +void MessageLoop::PostTask(already_AddRefed<Runnable> task) { + PostTask_Helper(Move(task), 0); } -void MessageLoop::PostIdleTask( - const tracked_objects::Location& from_here, Task* task) { +void MessageLoop::PostDelayedTask(already_AddRefed<Runnable> task, int delay_ms) { + PostTask_Helper(Move(task), delay_ms); +} + +void MessageLoop::PostIdleTask(already_AddRefed<Runnable> task) { DCHECK(current() == this); -#ifdef MOZ_TASK_TRACER - task = mozilla::tasktracer::CreateTracedTask(task); - (static_cast<mozilla::tasktracer::TracedTask*>(task))->DispatchTask(); -#endif - - task->SetBirthPlace(from_here); - PendingTask pending_task(task, false); - deferred_non_nestable_work_queue_.push(pending_task); + PendingTask pending_task(Move(task), false); + deferred_non_nestable_work_queue_.push(Move(pending_task)); } // Possibly called on a background thread! -void MessageLoop::PostTask_Helper( - const tracked_objects::Location& from_here, Task* task, int delay_ms) { - -#ifdef MOZ_TASK_TRACER - task = mozilla::tasktracer::CreateTracedTask(task); - (static_cast<mozilla::tasktracer::TracedTask*>(task))->DispatchTask(delay_ms); -#endif - - task->SetBirthPlace(from_here); - - PendingTask pending_task(task, true); +void MessageLoop::PostTask_Helper(already_AddRefed<Runnable> task, int delay_ms) { + PendingTask pending_task(Move(task), true); if (delay_ms > 0) { pending_task.delayed_run_time = TimeTicks::Now() + TimeDelta::FromMilliseconds(delay_ms); } else { DCHECK(delay_ms == 0) << "delay should not be negative"; } // Warning: Don't try to short-circuit, and handle this thread's tasks more // directly, as it could starve handling of foreign threads. Put every task // into this queue. RefPtr<base::MessagePump> pump; { AutoLock locked(incoming_queue_lock_); - incoming_queue_.push(pending_task); + incoming_queue_.push(Move(pending_task)); pump = pump_; } // Since the incoming_queue_ may contain a task that destroys this message // loop, we cannot exit incoming_queue_lock_ until we are done with |this|. // We use a stack-based reference to the message pump so that we can call // ScheduleWork outside of incoming_queue_lock_. pump->ScheduleWork(); @@ -336,49 +321,50 @@ void MessageLoop::ScheduleWork() { } bool MessageLoop::NestableTasksAllowed() const { return nestable_tasks_allowed_; } //------------------------------------------------------------------------------ -void MessageLoop::RunTask(Task* task) { +void MessageLoop::RunTask(already_AddRefed<Runnable> aTask) { DCHECK(nestable_tasks_allowed_); // Execute the task and assume the worst: It is probably not reentrant. nestable_tasks_allowed_ = false; + RefPtr<Runnable> task = aTask; task->Run(); - delete task; + task = nullptr; nestable_tasks_allowed_ = true; } -bool MessageLoop::DeferOrRunPendingTask(const PendingTask& pending_task) { +bool MessageLoop::DeferOrRunPendingTask(PendingTask&& pending_task) { if (pending_task.nestable || state_->run_depth <= run_depth_base_) { - RunTask(pending_task.task); + RunTask(pending_task.task.forget()); // Show that we ran a task (Note: a new one might arrive as a // consequence!). return true; } // We couldn't run the task now because we're in a nested message loop // and the task isn't nestable. - deferred_non_nestable_work_queue_.push(pending_task); + deferred_non_nestable_work_queue_.push(Move(pending_task)); return false; } void MessageLoop::AddToDelayedWorkQueue(const PendingTask& pending_task) { // Move to the delayed work queue. Initialize the sequence number // before inserting into the delayed_work_queue_. The sequence number // is used to faciliate FIFO sorting when two tasks have the same // delayed_run_time value. PendingTask new_pending_task(pending_task); new_pending_task.sequence_num = next_sequence_num_++; - delayed_work_queue_.push(new_pending_task); + delayed_work_queue_.push(Move(new_pending_task)); } void MessageLoop::ReloadWorkQueue() { // We can improve performance of our loading tasks from incoming_queue_ to // work_queue_ by waiting until the last minute (work_queue_ is empty) to // load. That reduces the number of locks-per-task significantly when our // queues get large. if (!work_queue_.empty()) @@ -390,37 +376,24 @@ void MessageLoop::ReloadWorkQueue() { if (incoming_queue_.empty()) return; std::swap(incoming_queue_, work_queue_); DCHECK(incoming_queue_.empty()); } } bool MessageLoop::DeletePendingTasks() { -#ifdef DEBUG - if (!work_queue_.empty()) { - Task* task = work_queue_.front().task; - tracked_objects::Location loc = task->GetBirthPlace(); - printf("Unexpected task! %s:%s:%d\n", - loc.function_name(), loc.file_name(), loc.line_number()); - } -#endif - MOZ_ASSERT(work_queue_.empty()); bool did_work = !deferred_non_nestable_work_queue_.empty(); while (!deferred_non_nestable_work_queue_.empty()) { - Task* task = deferred_non_nestable_work_queue_.front().task; deferred_non_nestable_work_queue_.pop(); - delete task; } did_work |= !delayed_work_queue_.empty(); while (!delayed_work_queue_.empty()) { - Task* task = delayed_work_queue_.top().task; delayed_work_queue_.pop(); - delete task; } return did_work; } bool MessageLoop::DoWork() { if (!nestable_tasks_allowed_) { // Task can't be executed right now. return false; @@ -428,25 +401,26 @@ bool MessageLoop::DoWork() { for (;;) { ReloadWorkQueue(); if (work_queue_.empty()) break; // Execute oldest task. do { - PendingTask pending_task = work_queue_.front(); + PendingTask pending_task = Move(work_queue_.front()); work_queue_.pop(); if (!pending_task.delayed_run_time.is_null()) { + // NB: Don't move, because we use this later! AddToDelayedWorkQueue(pending_task); // If we changed the topmost task, then it is time to re-schedule. if (delayed_work_queue_.top().task == pending_task.task) pump_->ScheduleDelayedWork(pending_task.delayed_run_time); } else { - if (DeferOrRunPendingTask(pending_task)) + if (DeferOrRunPendingTask(Move(pending_task))) return true; } } while (!work_queue_.empty()); } // Nothing happened. return false; } @@ -463,17 +437,17 @@ bool MessageLoop::DoDelayedWork(TimeTick } PendingTask pending_task = delayed_work_queue_.top(); delayed_work_queue_.pop(); if (!delayed_work_queue_.empty()) *next_delayed_work_time = delayed_work_queue_.top().delayed_run_time; - return DeferOrRunPendingTask(pending_task); + return DeferOrRunPendingTask(Move(pending_task)); } bool MessageLoop::DoIdleWork() { if (ProcessNextDelayedNonNestableTask()) return true; if (state_->quit_received) pump_->Quit();
--- a/ipc/chromium/src/base/message_loop.h +++ b/ipc/chromium/src/base/message_loop.h @@ -106,25 +106,22 @@ public: // such tasks get deferred until the top-most MessageLoop::Run is executing. // // The MessageLoop takes ownership of the Task, and deletes it after it has // been Run(). // // NOTE: These methods may be called on any thread. The Task will be invoked // on the thread that executes MessageLoop::Run(). - void PostTask( - const tracked_objects::Location& from_here, Task* task); + void PostTask(already_AddRefed<mozilla::Runnable> task); - void PostDelayedTask( - const tracked_objects::Location& from_here, Task* task, int delay_ms); + void PostDelayedTask(already_AddRefed<mozilla::Runnable> task, int delay_ms); // PostIdleTask is not thread safe and should be called on this thread - void PostIdleTask( - const tracked_objects::Location& from_here, Task* task); + void PostIdleTask(already_AddRefed<mozilla::Runnable> task); // Run the message loop. void Run(); // Signals the Run method to return after it is done processing all pending // messages. This method may only be called on the same thread that called // Run, and Run must still be on the call stack. // @@ -132,20 +129,21 @@ public: // that doing so is fairly dangerous if the target thread makes nested calls // to MessageLoop::Run. The problem being that you won't know which nested // run loop you are quiting, so be careful! // void Quit(); // Invokes Quit on the current MessageLoop when run. Useful to schedule an // arbitrary MessageLoop to Quit. - class QuitTask : public Task { + class QuitTask : public mozilla::Runnable { public: - virtual void Run() override { + NS_IMETHOD Run() override { MessageLoop::current()->Quit(); + return NS_OK; } }; // A MessageLoop has a particular type, which indicates the set of // asynchronous events it may process in addition to tasks and timers. // // TYPE_DEFAULT // This type of ML only supports tasks and timers. @@ -277,25 +275,48 @@ public: ~AutoRunState(); private: MessageLoop* loop_; RunState* previous_state_; }; // This structure is copied around by value. struct PendingTask { - Task* task; // The task to run. + RefPtr<mozilla::Runnable> task; // The task to run. base::TimeTicks delayed_run_time; // The time when the task should be run. int sequence_num; // Secondary sort key for run time. bool nestable; // OK to dispatch from a nested loop. - PendingTask(Task* aTask, bool aNestable) + PendingTask(already_AddRefed<mozilla::Runnable> aTask, bool aNestable) : task(aTask), sequence_num(0), nestable(aNestable) { } + PendingTask(PendingTask&& aOther) + : task(aOther.task.forget()), + delayed_run_time(aOther.delayed_run_time), + sequence_num(aOther.sequence_num), + nestable(aOther.nestable) { + } + + // std::priority_queue<T>::top is dumb, so we have to have this. + PendingTask(const PendingTask& aOther) + : task(aOther.task), + delayed_run_time(aOther.delayed_run_time), + sequence_num(aOther.sequence_num), + nestable(aOther.nestable) { + } + PendingTask& operator=(const PendingTask& aOther) + { + task = aOther.task; + delayed_run_time = aOther.delayed_run_time; + sequence_num = aOther.sequence_num; + nestable = aOther.nestable; + return *this; + } + // Used to support sorting. bool operator<(const PendingTask& other) const; }; typedef std::queue<PendingTask> TaskQueue; typedef std::priority_queue<PendingTask> DelayedTaskQueue; #if defined(OS_WIN) @@ -327,41 +348,40 @@ public: // PostTask). If there are queued tasks, the oldest one is executed and // new_task is queued. new_task is optional and can be NULL. In this NULL // case, the method will run one pending task (if any exist). Returns true if // it executes a task. Queued tasks accumulate only when there is a // non-nestable task currently processing, in which case the new_task is // appended to the list work_queue_. Such re-entrancy generally happens when // an unrequested message pump (typical of a native dialog) is executing in // the context of a task. - bool QueueOrRunTask(Task* new_task); + bool QueueOrRunTask(already_AddRefed<mozilla::Runnable> new_task); // Runs the specified task and deletes it. - void RunTask(Task* task); + void RunTask(already_AddRefed<mozilla::Runnable> task); // Calls RunTask or queues the pending_task on the deferred task list if it // cannot be run right now. Returns true if the task was run. - bool DeferOrRunPendingTask(const PendingTask& pending_task); + bool DeferOrRunPendingTask(PendingTask&& pending_task); // Adds the pending task to delayed_work_queue_. void AddToDelayedWorkQueue(const PendingTask& pending_task); // Load tasks from the incoming_queue_ into work_queue_ if the latter is // empty. The former requires a lock to access, while the latter is directly // accessible on this thread. void ReloadWorkQueue(); // Delete tasks that haven't run yet without running them. Used in the // destructor to make sure all the task's destructors get called. Returns // true if some work was done. bool DeletePendingTasks(); // Post a task to our incomming queue. - void PostTask_Helper(const tracked_objects::Location& from_here, Task* task, - int delay_ms); + void PostTask_Helper(already_AddRefed<mozilla::Runnable> task, int delay_ms); // base::MessagePump::Delegate methods: virtual bool DoWork() override; virtual bool DoDelayedWork(base::TimeTicks* next_delayed_work_time) override; virtual bool DoIdleWork() override; Type type_; int32_t id_;
--- a/ipc/chromium/src/base/object_watcher.cc +++ b/ipc/chromium/src/base/object_watcher.cc @@ -5,34 +5,37 @@ #include "base/object_watcher.h" #include "base/logging.h" namespace base { //----------------------------------------------------------------------------- -struct ObjectWatcher::Watch : public Task { +class ObjectWatcher::Watch : public mozilla::Runnable { +public: ObjectWatcher* watcher; // The associated ObjectWatcher instance HANDLE object; // The object being watched HANDLE wait_object; // Returned by RegisterWaitForSingleObject MessageLoop* origin_loop; // Used to get back to the origin thread Delegate* delegate; // Delegate to notify when signaled bool did_signal; // DoneWaiting was called - virtual void Run() { + NS_IMETHOD Run() override { // The watcher may have already been torn down, in which case we need to // just get out of dodge. if (!watcher) - return; + return NS_OK; DCHECK(did_signal); watcher->StopWatching(); delegate->OnObjectSignaled(object); + + return NS_OK; } }; //----------------------------------------------------------------------------- ObjectWatcher::ObjectWatcher() : watch_(NULL) { } @@ -41,35 +44,34 @@ ObjectWatcher::~ObjectWatcher() { } bool ObjectWatcher::StartWatching(HANDLE object, Delegate* delegate) { if (watch_) { NOTREACHED() << "Already watching an object"; return false; } - Watch* watch = new Watch; + RefPtr<Watch> watch = new Watch; watch->watcher = this; watch->object = object; watch->origin_loop = MessageLoop::current(); watch->delegate = delegate; watch->did_signal = false; // Since our job is to just notice when an object is signaled and report the // result back to this thread, we can just run on a Windows wait thread. DWORD wait_flags = WT_EXECUTEDEFAULT | WT_EXECUTEONLYONCE; if (!RegisterWaitForSingleObject(&watch->wait_object, object, DoneWaiting, - watch, INFINITE, wait_flags)) { + watch.get(), INFINITE, wait_flags)) { NOTREACHED() << "RegisterWaitForSingleObject failed: " << GetLastError(); - delete watch; return false; } - watch_ = watch; + watch_ = watch.forget(); // We need to know if the current message loop is going away so we can // prevent the wait thread from trying to access a dead message loop. MessageLoop::current()->AddDestructionObserver(this); return true; } bool ObjectWatcher::StopWatching() { @@ -90,22 +92,16 @@ bool ObjectWatcher::StopWatching() { // since we expect that UnregisterWaitEx resulted in a memory barrier, but // just to be sure, we're going to be explicit. MemoryBarrier(); // If the watch has been posted, then we need to make sure it knows not to do // anything once it is run. watch_->watcher = NULL; - // If DoneWaiting was called, then the watch would have been posted as a - // task, and will therefore be deleted by the MessageLoop. Otherwise, we - // need to take care to delete it here. - if (!watch_->did_signal) - delete watch_; - watch_ = NULL; MessageLoop::current()->RemoveDestructionObserver(this); return true; } HANDLE ObjectWatcher::GetWatchedObject() { if (!watch_) @@ -114,24 +110,25 @@ HANDLE ObjectWatcher::GetWatchedObject() return watch_->object; } // static void CALLBACK ObjectWatcher::DoneWaiting(void* param, BOOLEAN timed_out) { DCHECK(!timed_out); Watch* watch = static_cast<Watch*>(param); + RefPtr<Watch> addrefedWatch = watch; // Record that we ran this function. watch->did_signal = true; // We rely on the locking in PostTask() to ensure that a memory barrier is // provided, which in turn ensures our change to did_signal can be observed // on the target thread. - watch->origin_loop->PostTask(FROM_HERE, watch); + watch->origin_loop->PostTask(addrefedWatch.forget()); } void ObjectWatcher::WillDestroyCurrentMessageLoop() { // Need to shutdown the watch so that we don't try to access the MessageLoop // after this point. StopWatching(); }
--- a/ipc/chromium/src/base/object_watcher.h +++ b/ipc/chromium/src/base/object_watcher.h @@ -78,17 +78,17 @@ class ObjectWatcher : public MessageLoop private: // Called on a background thread when done waiting. static void CALLBACK DoneWaiting(void* param, BOOLEAN timed_out); // MessageLoop::DestructionObserver implementation: virtual void WillDestroyCurrentMessageLoop(); // Internal state. - struct Watch; - Watch* watch_; + class Watch; + RefPtr<Watch> watch_; DISALLOW_COPY_AND_ASSIGN(ObjectWatcher); }; } // namespace base #endif // BASE_OBJECT_WATCHER_H_
--- a/ipc/chromium/src/base/task.h +++ b/ipc/chromium/src/base/task.h @@ -2,21 +2,21 @@ // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef BASE_TASK_H_ #define BASE_TASK_H_ #include "base/revocable_store.h" -#include "base/tracked.h" #include "base/tuple.h" #include "mozilla/IndexSequence.h" #include "mozilla/Tuple.h" #include "nsISupportsImpl.h" +#include "nsThreadUtils.h" // Helper functions so that we can call a function a pass it arguments that come // from a Tuple. namespace details { // Call the given method on the given object. Arguments are passed by move // semantics from the given tuple. If the tuple has length N, the sequence must @@ -50,36 +50,16 @@ void DispatchTupleToMethod(ObjT* obj, Me // Same as above, but call a function. template<typename Function, typename... Args> void DispatchTupleToFunction(Function function, mozilla::Tuple<Args...>& arg) { details::CallFunction(typename mozilla::IndexSequenceFor<Args...>::Type(), function, arg); } -// Task ------------------------------------------------------------------------ -// -// A task is a generic runnable thingy, usually used for running code on a -// different thread or for scheduling future tasks off of the message loop. - -class Task : public tracked_objects::Tracked { - public: - Task() {} - virtual ~Task() {} - - // Tasks are automatically deleted after Run is called. - virtual void Run() = 0; -}; - -class CancelableTask : public Task { - public: - // Not all tasks support cancellation. - virtual void Cancel() = 0; -}; - // Scoped Factories ------------------------------------------------------------ // // These scoped factory objects can be used by non-refcounted objects to safely // place tasks in a message loop. Each factory guarantees that the tasks it // produces will not run after the factory is destroyed. Commonly, factories // are declared as class members, so the class' tasks will automatically cancel // when the class instance is destroyed. // @@ -105,17 +85,17 @@ class CancelableTask : public Task { // void ScheduleSomeMethod() { // // If you'd like to only only have one pending task at a time, test for // // |empty| before manufacturing another task. // if (!some_method_factory_.empty()) // return; // // // The factories are not thread safe, so always invoke on // // |MessageLoop::current()|. -// MessageLoop::current()->PostDelayedTask(FROM_HERE, +// MessageLoop::current()->PostDelayedTask( // some_method_factory_.NewRunnableMethod(&MyClass::SomeMethod), // kSomeMethodDelayMS); // } // }; // A ScopedTaskFactory produces tasks of type |TaskType| and prevents them from // running after it is destroyed. template<class TaskType> @@ -127,19 +107,20 @@ class ScopedTaskFactory : public Revocab inline TaskType* NewTask() { return new TaskWrapper(this); } class TaskWrapper : public TaskType { public: explicit TaskWrapper(RevocableStore* store) : revocable_(store) { } - virtual void Run() { + NS_IMETHOD Run() override { if (!revocable_.revoked()) TaskType::Run(); + return NS_OK; } ~TaskWrapper() { NS_ASSERT_OWNINGTHREAD(TaskWrapper); } private: Revocable revocable_; @@ -157,39 +138,43 @@ class ScopedTaskFactory : public Revocab // object. This is particularly useful for generating callbacks for // non-reference counted objects when the factory is a member of the object. template<class T> class ScopedRunnableMethodFactory : public RevocableStore { public: explicit ScopedRunnableMethodFactory(T* object) : object_(object) { } template <class Method, typename... Elements> - inline Task* NewRunnableMethod(Method method, Elements&&... elements) { + inline already_AddRefed<mozilla::Runnable> + NewRunnableMethod(Method method, Elements&&... elements) { typedef mozilla::Tuple<typename mozilla::Decay<Elements>::Type...> ArgsTuple; typedef RunnableMethod<Method, ArgsTuple> Runnable; typedef typename ScopedTaskFactory<Runnable>::TaskWrapper TaskWrapper; - TaskWrapper* task = new TaskWrapper(this); + RefPtr<TaskWrapper> task = new TaskWrapper(this); task->Init(object_, method, mozilla::MakeTuple(mozilla::Forward<Elements>(elements)...)); - return task; + return task.forget(); } protected: template <class Method, class Params> - class RunnableMethod : public Task { + class RunnableMethod : public mozilla::Runnable { public: RunnableMethod() { } void Init(T* obj, Method meth, Params&& params) { obj_ = obj; meth_ = meth; params_ = mozilla::Forward<Params>(params); } - virtual void Run() { DispatchTupleToMethod(obj_, meth_, params_); } + NS_IMETHOD Run() override { + DispatchTupleToMethod(obj_, meth_, params_); + return NS_OK; + } private: T* MOZ_UNSAFE_REF("The validity of this pointer must be enforced by " "external factors.") obj_; Method meth_; Params params_; DISALLOW_EVIL_CONSTRUCTORS(RunnableMethod); @@ -200,25 +185,27 @@ class ScopedRunnableMethodFactory : publ DISALLOW_EVIL_CONSTRUCTORS(ScopedRunnableMethodFactory); }; // General task implementations ------------------------------------------------ // Task to delete an object template<class T> -class DeleteTask : public CancelableTask { +class DeleteTask : public mozilla::CancelableRunnable { public: explicit DeleteTask(T* obj) : obj_(obj) { } - virtual void Run() { + NS_IMETHOD Run() override { delete obj_; + return NS_OK; } - virtual void Cancel() { + virtual nsresult Cancel() override { obj_ = NULL; + return NS_OK; } private: T* MOZ_UNSAFE_REF("The validity of this pointer must be enforced by " "external factors.") obj_; }; // RunnableMethodTraits -------------------------------------------------------- // @@ -268,40 +255,42 @@ struct RunnableMethodTraits<const T> { // A - the first parameter (if any) to the method // B - the second parameter (if any) to the mathod // // Put these all together and you get an object that can call a method whose // signature is: // R T::MyFunction([A[, B]]) // // Usage: -// PostTask(FROM_HERE, NewRunnableMethod(object, &Object::method[, a[, b]]) -// PostTask(FROM_HERE, NewRunnableFunction(&function[, a[, b]]) +// PostTask(NewRunnableMethod(object, &Object::method[, a[, b]]) +// PostTask(NewRunnableFunction(&function[, a[, b]]) // RunnableMethod and NewRunnableMethod implementation ------------------------- template <class T, class Method, class Params> -class RunnableMethod : public CancelableTask, +class RunnableMethod : public mozilla::CancelableRunnable, public RunnableMethodTraits<T> { public: RunnableMethod(T* obj, Method meth, Params&& params) : obj_(obj), meth_(meth), params_(mozilla::Forward<Params>(params)) { this->RetainCallee(obj_); } ~RunnableMethod() { ReleaseCallee(); } - virtual void Run() { + NS_IMETHOD Run() override { if (obj_) DispatchTupleToMethod(obj_, meth_, params_); + return NS_OK; } - virtual void Cancel() { + virtual nsresult Cancel() override { ReleaseCallee(); + return NS_OK; } private: void ReleaseCallee() { if (obj_) { RunnableMethodTraits<T>::ReleaseCallee(obj_); obj_ = nullptr; } @@ -310,47 +299,55 @@ class RunnableMethod : public Cancelable // This is owning because of the RetainCallee and ReleaseCallee calls in the // constructor and destructor. T* MOZ_OWNING_REF obj_; Method meth_; Params params_; }; template <class T, class Method, typename... Args> -inline CancelableTask* NewRunnableMethod(T* object, Method method, Args&&... args) { +inline already_AddRefed<mozilla::CancelableRunnable> +NewRunnableMethod(T* object, Method method, Args&&... args) { typedef mozilla::Tuple<typename mozilla::Decay<Args>::Type...> ArgsTuple; - return new RunnableMethod<T, Method, ArgsTuple>( - object, method, mozilla::MakeTuple(mozilla::Forward<Args>(args)...)); + RefPtr<mozilla::CancelableRunnable> t = + new RunnableMethod<T, Method, ArgsTuple>(object, method, + mozilla::MakeTuple(mozilla::Forward<Args>(args)...)); + return t.forget(); } // RunnableFunction and NewRunnableFunction implementation --------------------- template <class Function, class Params> -class RunnableFunction : public CancelableTask { +class RunnableFunction : public mozilla::CancelableRunnable { public: RunnableFunction(Function function, Params&& params) : function_(function), params_(mozilla::Forward<Params>(params)) { } ~RunnableFunction() { } - virtual void Run() { + NS_IMETHOD Run() override { if (function_) DispatchTupleToFunction(function_, params_); + return NS_OK; } - virtual void Cancel() { + virtual nsresult Cancel() override { function_ = nullptr; + return NS_OK; } Function function_; Params params_; }; template <class Function, typename... Args> -inline CancelableTask* NewRunnableFunction(Function function, Args&&... args) { +inline already_AddRefed<mozilla::CancelableRunnable> +NewRunnableFunction(Function function, Args&&... args) { typedef mozilla::Tuple<typename mozilla::Decay<Args>::Type...> ArgsTuple; - return new RunnableFunction<Function, ArgsTuple>( - function, mozilla::MakeTuple(mozilla::Forward<Args>(args)...)); + RefPtr<mozilla::CancelableRunnable> t = + new RunnableFunction<Function, ArgsTuple>(function, + mozilla::MakeTuple(mozilla::Forward<Args>(args)...)); + return t.forget(); } #endif // BASE_TASK_H_
--- a/ipc/chromium/src/base/thread.cc +++ b/ipc/chromium/src/base/thread.cc @@ -13,21 +13,22 @@ #ifdef MOZ_TASK_TRACER #include "GeckoTaskTracer.h" #endif namespace base { // This task is used to trigger the message loop to exit. -class ThreadQuitTask : public Task { +class ThreadQuitTask : public mozilla::Runnable { public: - virtual void Run() { + NS_IMETHOD Run() override { MessageLoop::current()->Quit(); Thread::SetThreadWasQuitProperly(true); + return NS_OK; } }; // Used to pass data to ThreadMain. This structure is allocated on the stack // from within StartWithOptions. struct Thread::StartupData { // We get away with a const reference here because of how we are allocated. const Thread::Options& options; @@ -108,18 +109,20 @@ bool Thread::StartWithOptions(const Opti void Thread::Stop() { if (!thread_was_started()) return; // We should only be called on the same thread that started us. DCHECK_NE(thread_id_, PlatformThread::CurrentId()); // StopSoon may have already been called. - if (message_loop_) - message_loop_->PostTask(FROM_HERE, new ThreadQuitTask()); + if (message_loop_) { + RefPtr<ThreadQuitTask> task = new ThreadQuitTask(); + message_loop_->PostTask(task.forget()); + } // Wait for the thread to exit. It should already have terminated but make // sure this assumption is valid. // // TODO(darin): Unfortunately, we need to keep message_loop_ around until // the thread exits. Some consumers are abusing the API. Make them stop. // PlatformThread::Join(thread_); @@ -138,17 +141,18 @@ void Thread::StopSoon() { // We should only be called on the same thread that started us. DCHECK_NE(thread_id_, PlatformThread::CurrentId()); // We had better have a message loop at this point! If we do not, then it // most likely means that the thread terminated unexpectedly, probably due // to someone calling Quit() on our message loop directly. DCHECK(message_loop_); - message_loop_->PostTask(FROM_HERE, new ThreadQuitTask()); + RefPtr<ThreadQuitTask> task = new ThreadQuitTask(); + message_loop_->PostTask(task.forget()); } void Thread::ThreadMain() { char aLocal; profiler_register_thread(name_.c_str(), &aLocal); mozilla::IOInterposer::RegisterCurrentThread(); // The message loop for this thread.
--- a/ipc/chromium/src/base/timer.cc +++ b/ipc/chromium/src/base/timer.cc @@ -15,14 +15,15 @@ void BaseTimer_Helper::OrphanDelayedTask } } void BaseTimer_Helper::InitiateDelayedTask(TimerTask* timer_task) { OrphanDelayedTask(); delayed_task_ = timer_task; delayed_task_->timer_ = this; + RefPtr<TimerTask> addrefedTask = timer_task; MessageLoop::current()->PostDelayedTask( - FROM_HERE, timer_task, + addrefedTask.forget(), static_cast<int>(timer_task->delay_.InMilliseconds())); } } // namespace base
--- a/ipc/chromium/src/base/timer.h +++ b/ipc/chromium/src/base/timer.h @@ -64,48 +64,48 @@ class BaseTimer_Helper { public: // Stops the timer. ~BaseTimer_Helper() { OrphanDelayedTask(); } // Returns true if the timer is running (i.e., not stopped). bool IsRunning() const { - return delayed_task_ != NULL; + return !!delayed_task_; } // Returns the current delay for this timer. May only call this method when // the timer is running! TimeDelta GetCurrentDelay() const { DCHECK(IsRunning()); return delayed_task_->delay_; } protected: - BaseTimer_Helper() : delayed_task_(NULL) {} + BaseTimer_Helper() {} // We have access to the timer_ member so we can orphan this task. - class TimerTask : public Task { + class TimerTask : public mozilla::Runnable { public: explicit TimerTask(TimeDelta delay) : delay_(delay) { // timer_ is set in InitiateDelayedTask. } virtual ~TimerTask() {} BaseTimer_Helper* timer_; TimeDelta delay_; }; // Used to orphan delayed_task_ so that when it runs it does nothing. void OrphanDelayedTask(); // Used to initiated a new delayed task. This has the side-effect of // orphaning delayed_task_ if it is non-null. void InitiateDelayedTask(TimerTask* timer_task); - TimerTask* delayed_task_; + RefPtr<TimerTask> delayed_task_; DISALLOW_COPY_AND_ASSIGN(BaseTimer_Helper); }; //----------------------------------------------------------------------------- // This class is an implementation detail of OneShotTimer and RepeatingTimer. // Please do not use this class directly. template <class Receiver, bool kIsRepeating> @@ -124,17 +124,17 @@ class BaseTimer : public BaseTimer_Helpe // running. void Stop() { OrphanDelayedTask(); } // Call this method to reset the timer delay of an already running timer. void Reset() { DCHECK(IsRunning()); - InitiateDelayedTask(static_cast<TimerTask*>(delayed_task_)->Clone()); + InitiateDelayedTask(static_cast<TimerTask*>(delayed_task_.get())->Clone()); } private: typedef BaseTimer<Receiver, kIsRepeating> SelfType; class TimerTask : public BaseTimer_Helper::TimerTask { public: TimerTask(TimeDelta delay, Receiver* receiver, ReceiverMethod method) @@ -145,24 +145,25 @@ class BaseTimer : public BaseTimer_Helpe virtual ~TimerTask() { // This task may be getting cleared because the MessageLoop has been // destructed. If so, don't leave the Timer with a dangling pointer // to this now-defunct task. ClearBaseTimer(); } - virtual void Run() { + NS_IMETHOD Run() override { if (!timer_) // timer_ is null if we were orphaned. - return; + return NS_OK; if (kIsRepeating) ResetBaseTimer(); else ClearBaseTimer(); DispatchToMethod(receiver_, method_, Tuple0()); + return NS_OK; } TimerTask* Clone() const { return new TimerTask(delay_, receiver_, method_); } private: // Inform the Base that the timer is no longer active.
deleted file mode 100644 --- a/ipc/chromium/src/base/tracked.cc +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/tracked.h" - -#include "base/string_util.h" -#include "base/tracked_objects.h" - -using base::Time; - -namespace tracked_objects { - -//------------------------------------------------------------------------------ -void Location::Write(bool display_filename, bool display_function_name, - std::string* output) const { - StringAppendF(output, "%s[%d] ", - display_filename ? file_name_ : "line", - line_number_); - - if (display_function_name) { - WriteFunctionName(output); - output->push_back(' '); - } -} - -void Location::WriteFunctionName(std::string* output) const { - // Translate "<" to "<" for HTML safety. - // TODO(jar): Support ASCII or html for logging in ASCII. - for (const char *p = function_name_; *p; p++) { - switch (*p) { - case '<': - output->append("<"); - break; - - case '>': - output->append(">"); - break; - - default: - output->push_back(*p); - break; - } - } -} - -//------------------------------------------------------------------------------ - -#ifndef TRACK_ALL_TASK_OBJECTS - -Tracked::Tracked() {} -Tracked::~Tracked() {} -void Tracked::SetBirthPlace(const Location& from_here) {} -bool Tracked::MissingBirthplace() const { return false; } -void Tracked::ResetBirthTime() {} - -#else - -Tracked::Tracked() : tracked_births_(NULL), tracked_birth_time_(Time::Now()) { - if (!ThreadData::IsActive()) - return; - SetBirthPlace(Location("NoFunctionName", "NeedToSetBirthPlace", -1)); -} - -Tracked::~Tracked() { - if (!ThreadData::IsActive() || !tracked_births_) - return; - ThreadData::current()->TallyADeath(*tracked_births_, - Time::Now() - tracked_birth_time_); -} - -void Tracked::SetBirthPlace(const Location& from_here) { - if (!ThreadData::IsActive()) - return; - if (tracked_births_) - tracked_births_->ForgetBirth(); - ThreadData* current_thread_data = ThreadData::current(); - if (!current_thread_data) - return; // Shutdown started, and this thread wasn't registered. - tracked_births_ = current_thread_data->FindLifetime(from_here); - tracked_births_->RecordBirth(); -} - -Location Tracked::GetBirthPlace() const { - if (tracked_births_) { - return tracked_births_->location(); - } - return Location(); -} - -void Tracked::ResetBirthTime() { - tracked_birth_time_ = Time::Now(); -} - -bool Tracked::MissingBirthplace() const { - return -1 == tracked_births_->location().line_number(); -} - -#endif // NDEBUG - -} // namespace tracked_objects
deleted file mode 100644 --- a/ipc/chromium/src/base/tracked.h +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -//------------------------------------------------------------------------------ -// Tracked is the base class for all tracked objects. During construction, it -// registers the fact that an instance was created, and at destruction time, it -// records that event. The instance may be tagged with a name, which is refered -// to as its Location. The Location is a file and line number, most -// typically indicated where the object was constructed. In some cases, as the -// object's significance is refined (for example, a Task object is augmented to -// do additonal things), its Location may be redefined to that later location. - -// Tracking includes (for each instance) recording the birth thread, death -// thread, and duration of life (from construction to destruction). All this -// data is accumulated and filtered for review at about:objects. - -#ifndef BASE_TRACKED_H_ -#define BASE_TRACKED_H_ - -#include <string> - -#include "base/time.h" - -#ifndef NDEBUG -#ifndef TRACK_ALL_TASK_OBJECTS -#define TRACK_ALL_TASK_OBJECTS -#endif // TRACK_ALL_TASK_OBJECTS -#endif // NDEBUG - -namespace tracked_objects { - -//------------------------------------------------------------------------------ -// Location provides basic info where of an object was constructed, or was -// significantly brought to life. - -class Location { - public: - // Constructor should be called with a long-lived char*, such as __FILE__. - // It assumes the provided value will persist as a global constant, and it - // will not make a copy of it. - Location(const char* aFunctionName, const char* aFilename, int aLineNumber) - : function_name_(aFunctionName), - file_name_(aFilename), - line_number_(aLineNumber) { } - - // Provide a default constructor for easy of debugging. - Location() - : function_name_("Unknown"), - file_name_("Unknown"), - line_number_(-1) { } - - // Comparison operator for insertion into a std::map<> hash tables. - // All we need is *some* (any) hashing distinction. Strings should already - // be unique, so we don't bother with strcmp or such. - // Use line number as the primary key (because it is fast, and usually gets us - // a difference), and then pointers as secondary keys (just to get some - // distinctions). - bool operator < (const Location& other) const { - if (line_number_ != other.line_number_) - return line_number_ < other.line_number_; - if (file_name_ != other.file_name_) - return file_name_ < other.file_name_; - return function_name_ < other.function_name_; - } - - const char* function_name() const { return function_name_; } - const char* file_name() const { return file_name_; } - int line_number() const { return line_number_; } - - void Write(bool display_filename, bool display_function_name, - std::string* output) const; - - // Write function_name_ in HTML with '<' and '>' properly encoded. - void WriteFunctionName(std::string* output) const; - - private: - const char* const function_name_; - const char* const file_name_; - const int line_number_; -}; - - -//------------------------------------------------------------------------------ -// Define a macro to record the current source location. - -#define FROM_HERE tracked_objects::Location(__FUNCTION__, __FILE__, __LINE__) - - -//------------------------------------------------------------------------------ - - -class Births; - -class Tracked { - public: - Tracked(); - virtual ~Tracked(); - - // Used to record the FROM_HERE location of a caller. - void SetBirthPlace(const Location& from_here); - Location GetBirthPlace() const; - - // When a task sits around a long time, such as in a timer, or object watcher, - // this method should be called when the task becomes active, and its - // significant lifetime begins (and its waiting to be woken up has passed). - void ResetBirthTime(); - - bool MissingBirthplace() const; - - private: -#ifdef TRACK_ALL_TASK_OBJECTS - - // Pointer to instance were counts of objects with the same birth location - // (on the same thread) are stored. - Births* tracked_births_; - // The time this object was constructed. If its life consisted of a long - // waiting period, and then it became active, then this value is generally - // reset before the object begins it active life. - base::Time tracked_birth_time_; - -#endif // TRACK_ALL_TASK_OBJECTS - - DISALLOW_COPY_AND_ASSIGN(Tracked); -}; - -} // namespace tracked_objects - -#endif // BASE_TRACKED_H_
deleted file mode 100644 --- a/ipc/chromium/src/base/tracked_objects.cc +++ /dev/null @@ -1,758 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/tracked_objects.h" - -#include <math.h> -#if defined(OS_WIN) -#include <windows.h> -#endif - -#include "base/string_util.h" - -using base::TimeDelta; -using mozilla::StaticMutexAutoLock; - -namespace tracked_objects { - -// A TLS slot to the TrackRegistry for the current thread. -// static -TLSSlot ThreadData::tls_index_(base::LINKER_INITIALIZED); - -//------------------------------------------------------------------------------ -// Death data tallies durations when a death takes place. - -void DeathData::RecordDeath(const TimeDelta& duration) { - ++count_; - life_duration_ += duration; - int64_t milliseconds = duration.InMilliseconds(); - square_duration_ += milliseconds * milliseconds; -} - -int DeathData::AverageMsDuration() const { - return static_cast<int>(life_duration_.InMilliseconds() / count_); -} - -double DeathData::StandardDeviation() const { - double average = AverageMsDuration(); - double variance = static_cast<float>(square_duration_)/count_ - - average * average; - return sqrt(variance); -} - - -void DeathData::AddDeathData(const DeathData& other) { - count_ += other.count_; - life_duration_ += other.life_duration_; - square_duration_ += other.square_duration_; -} - -void DeathData::Write(std::string* output) const { - if (!count_) - return; - if (1 == count_) - StringAppendF(output, "(1)Life in %dms ", AverageMsDuration()); - else - StringAppendF(output, "(%d)Lives %dms/life ", count_, AverageMsDuration()); -} - -void DeathData::Clear() { - count_ = 0; - life_duration_ = TimeDelta(); - square_duration_ = 0; -} - -//------------------------------------------------------------------------------ - -BirthOnThread::BirthOnThread(const Location& location) - : location_(location), - birth_thread_(ThreadData::current()) { } - -//------------------------------------------------------------------------------ -Births::Births(const Location& location) - : BirthOnThread(location), - birth_count_(0) { } - -//------------------------------------------------------------------------------ -// ThreadData maintains the central data for all births and death. - -// static -ThreadData* ThreadData::first_ = NULL; -// static -mozilla::StaticMutex ThreadData::list_lock_; - -// static -ThreadData::Status ThreadData::status_ = ThreadData::UNINITIALIZED; - -ThreadData::ThreadData() : next_(NULL), message_loop_(MessageLoop::current()) {} - -// static -ThreadData* ThreadData::current() { - if (!tls_index_.initialized()) - return NULL; - - ThreadData* registry = static_cast<ThreadData*>(tls_index_.Get()); - if (!registry) { - // We have to create a new registry for ThreadData. - bool too_late_to_create = false; - { - registry = new ThreadData; - StaticMutexAutoLock lock(list_lock_); - // Use lock to insure we have most recent status. - if (!IsActive()) { - too_late_to_create = true; - } else { - // Use lock to insert into list. - registry->next_ = first_; - first_ = registry; - } - } // Release lock. - if (too_late_to_create) { - delete registry; - registry = NULL; - } else { - tls_index_.Set(registry); - } - } - return registry; -} - -Births* ThreadData::FindLifetime(const Location& location) { - if (!message_loop_) // In case message loop wasn't yet around... - message_loop_ = MessageLoop::current(); // Find it now. - - BirthMap::iterator it = birth_map_.find(location); - if (it != birth_map_.end()) - return it->second; - Births* tracker = new Births(location); - - // Lock since the map may get relocated now, and other threads sometimes - // snapshot it (but they lock before copying it). - AutoLock lock(lock_); - birth_map_[location] = tracker; - return tracker; -} - -void ThreadData::TallyADeath(const Births& lifetimes, - const TimeDelta& duration) { - if (!message_loop_) // In case message loop wasn't yet around... - message_loop_ = MessageLoop::current(); // Find it now. - - DeathMap::iterator it = death_map_.find(&lifetimes); - if (it != death_map_.end()) { - it->second.RecordDeath(duration); - return; - } - - AutoLock lock(lock_); // Lock since the map may get relocated now. - death_map_[&lifetimes].RecordDeath(duration); -} - -// static -ThreadData* ThreadData::first() { - StaticMutexAutoLock lock(list_lock_); - return first_; -} - -const std::string ThreadData::ThreadName() const { - if (message_loop_) - return message_loop_->thread_name(); - return "ThreadWithoutMessageLoop"; -} - -// This may be called from another thread. -void ThreadData::SnapshotBirthMap(BirthMap *output) const { - AutoLock lock(*const_cast<Lock*>(&lock_)); - for (BirthMap::const_iterator it = birth_map_.begin(); - it != birth_map_.end(); ++it) - (*output)[it->first] = it->second; -} - -// This may be called from another thread. -void ThreadData::SnapshotDeathMap(DeathMap *output) const { - AutoLock lock(*const_cast<Lock*>(&lock_)); - for (DeathMap::const_iterator it = death_map_.begin(); - it != death_map_.end(); ++it) - (*output)[it->first] = it->second; -} - -#ifdef OS_WIN -void ThreadData::RunOnAllThreads(void (*function)()) { - ThreadData* list = first(); // Get existing list. - - std::vector<MessageLoop*> message_loops; - for (ThreadData* it = list; it; it = it->next()) { - if (current() != it && it->message_loop()) - message_loops.push_back(it->message_loop()); - } - - ThreadSafeDownCounter* counter = - new ThreadSafeDownCounter(message_loops.size() + 1); // Extra one for us! - - HANDLE completion_handle = CreateEventW(NULL, false, false, NULL); - // Tell all other threads to run. - for (size_t i = 0; i < message_loops.size(); ++i) - message_loops[i]->PostTask(FROM_HERE, - new RunTheStatic(function, completion_handle, counter)); - - // Also run Task on our thread. - RunTheStatic local_task(function, completion_handle, counter); - local_task.Run(); - - WaitForSingleObject(completion_handle, INFINITE); - int ret_val = CloseHandle(completion_handle); - DCHECK(ret_val); -} -#endif - -// static -bool ThreadData::StartTracking(bool status) { -#ifndef TRACK_ALL_TASK_OBJECTS - return false; // Not compiled in. -#else - if (!status) { - StaticMutexAutoLock lock(list_lock_); - DCHECK(status_ == ACTIVE || status_ == SHUTDOWN); - status_ = SHUTDOWN; - return true; - } - StaticMutexAutoLock lock(list_lock_); - DCHECK(status_ == UNINITIALIZED); - CHECK(tls_index_.Initialize(NULL)); - status_ = ACTIVE; - return true; -#endif -} - -// static -bool ThreadData::IsActive() { - return status_ == ACTIVE; -} - -#ifdef OS_WIN -// static -void ThreadData::ShutdownMultiThreadTracking() { - // Using lock, guarantee that no new ThreadData instances will be created. - if (!StartTracking(false)) - return; - - RunOnAllThreads(ShutdownDisablingFurtherTracking); - - // Now the *only* threads that might change the database are the threads with - // no messages loops. They might still be adding data to their birth records, - // but since no objects are deleted on those threads, there will be no further - // access to to cross-thread data. - // We could do a cleanup on all threads except for the ones without - // MessageLoops, but we won't bother doing cleanup (destruction of data) yet. - return; -} -#endif - -// static -void ThreadData::ShutdownSingleThreadedCleanup() { - // We must be single threaded... but be careful anyway. - if (!StartTracking(false)) - return; - ThreadData* thread_data_list; - { - StaticMutexAutoLock lock(list_lock_); - thread_data_list = first_; - first_ = NULL; - } - - while (thread_data_list) { - ThreadData* next_thread_data = thread_data_list; - thread_data_list = thread_data_list->next(); - - for (BirthMap::iterator it = next_thread_data->birth_map_.begin(); - next_thread_data->birth_map_.end() != it; ++it) - delete it->second; // Delete the Birth Records. - next_thread_data->birth_map_.clear(); - next_thread_data->death_map_.clear(); - delete next_thread_data; // Includes all Death Records. - } - - CHECK(tls_index_.initialized()); - tls_index_.Free(); - DCHECK(!tls_index_.initialized()); - status_ = UNINITIALIZED; -} - -// static -void ThreadData::ShutdownDisablingFurtherTracking() { - // Redundantly set status SHUTDOWN on this thread. - if (!StartTracking(false)) - return; -} - - -//------------------------------------------------------------------------------ - -ThreadData::ThreadSafeDownCounter::ThreadSafeDownCounter(size_t count) - : remaining_count_(count) { - DCHECK(remaining_count_ > 0); -} - -bool ThreadData::ThreadSafeDownCounter::LastCaller() { - { - AutoLock lock(lock_); - if (--remaining_count_) - return false; - } // Release lock, so we can delete everything in this instance. - delete this; - return true; -} - -//------------------------------------------------------------------------------ -#ifdef OS_WIN -ThreadData::RunTheStatic::RunTheStatic(FunctionPointer function, - HANDLE completion_handle, - ThreadSafeDownCounter* counter) - : function_(function), - completion_handle_(completion_handle), - counter_(counter) { -} - -void ThreadData::RunTheStatic::Run() { - function_(); - if (counter_->LastCaller()) - SetEvent(completion_handle_); -} -#endif - -//------------------------------------------------------------------------------ -// Individual 3-tuple of birth (place and thread) along with death thread, and -// the accumulated stats for instances (DeathData). - -Snapshot::Snapshot(const BirthOnThread& birth_on_thread, - const ThreadData& death_thread, - const DeathData& death_data) - : birth_(&birth_on_thread), - death_thread_(&death_thread), - death_data_(death_data) { -} - -Snapshot::Snapshot(const BirthOnThread& birth_on_thread, int count) - : birth_(&birth_on_thread), - death_thread_(NULL), - death_data_(DeathData(count)) { -} - -const std::string Snapshot::DeathThreadName() const { - if (death_thread_) - return death_thread_->ThreadName(); - return "Still_Alive"; -} - -void Snapshot::Write(std::string* output) const { - death_data_.Write(output); - StringAppendF(output, "%s->%s ", - birth_->birth_thread()->ThreadName().c_str(), - death_thread_->ThreadName().c_str()); - birth_->location().Write(true, true, output); -} - -void Snapshot::Add(const Snapshot& other) { - death_data_.AddDeathData(other.death_data_); -} - -//------------------------------------------------------------------------------ -// DataCollector - -DataCollector::DataCollector() { - DCHECK(ThreadData::IsActive()); - - ThreadData* my_list = ThreadData::current()->first(); - - count_of_contributing_threads_ = 0; - for (ThreadData* thread_data = my_list; - thread_data; - thread_data = thread_data->next()) { - ++count_of_contributing_threads_; - } - - // Gather data serially. A different constructor could be used to do in - // parallel, and then invoke an OnCompletion task. - for (ThreadData* thread_data = my_list; - thread_data; - thread_data = thread_data->next()) { - Append(*thread_data); - } -} - -void DataCollector::Append(const ThreadData& thread_data) { - // Get copy of data (which is done under ThreadData's lock). - ThreadData::BirthMap birth_map; - thread_data.SnapshotBirthMap(&birth_map); - ThreadData::DeathMap death_map; - thread_data.SnapshotDeathMap(&death_map); - - // Use our lock to protect our accumulation activity. - AutoLock lock(accumulation_lock_); - - DCHECK(count_of_contributing_threads_); - - for (ThreadData::DeathMap::const_iterator it = death_map.begin(); - it != death_map.end(); ++it) { - collection_.push_back(Snapshot(*it->first, thread_data, it->second)); - global_birth_count_[it->first] -= it->first->birth_count(); - } - - for (ThreadData::BirthMap::const_iterator it = birth_map.begin(); - it != birth_map.end(); ++it) { - global_birth_count_[it->second] += it->second->birth_count(); - } - - --count_of_contributing_threads_; -} - -DataCollector::Collection* DataCollector::collection() { - DCHECK(!count_of_contributing_threads_); - return &collection_; -} - -void DataCollector::AddListOfLivingObjects() { - DCHECK(!count_of_contributing_threads_); - for (BirthCount::iterator it = global_birth_count_.begin(); - it != global_birth_count_.end(); ++it) { - if (it->second > 0) - collection_.push_back(Snapshot(*it->first, it->second)); - } -} - -//------------------------------------------------------------------------------ -// Aggregation - -void Aggregation::AddDeathSnapshot(const Snapshot& snapshot) { - AddBirth(snapshot.birth()); - death_threads_[snapshot.death_thread()]++; - AddDeathData(snapshot.death_data()); -} - -void Aggregation::AddBirths(const Births& births) { - AddBirth(births); - birth_count_ += births.birth_count(); -} -void Aggregation::AddBirth(const BirthOnThread& birth) { - AddBirthPlace(birth.location()); - birth_threads_[birth.birth_thread()]++; -} - -void Aggregation::AddBirthPlace(const Location& location) { - locations_[location]++; - birth_files_[location.file_name()]++; -} - -void Aggregation::Write(std::string* output) const { - if (locations_.size() == 1) { - locations_.begin()->first.Write(true, true, output); - } else { - StringAppendF(output, "%d Locations. ", locations_.size()); - if (birth_files_.size() > 1) - StringAppendF(output, "%d Files. ", birth_files_.size()); - else - StringAppendF(output, "All born in %s. ", - birth_files_.begin()->first.c_str()); - } - - if (birth_threads_.size() > 1) - StringAppendF(output, "%d BirthingThreads. ", birth_threads_.size()); - else - StringAppendF(output, "All born on %s. ", - birth_threads_.begin()->first->ThreadName().c_str()); - - if (death_threads_.size() > 1) { - StringAppendF(output, "%d DeathThreads. ", death_threads_.size()); - } else { - if (death_threads_.begin()->first) - StringAppendF(output, "All deleted on %s. ", - death_threads_.begin()->first->ThreadName().c_str()); - else - output->append("All these objects are still alive."); - } - - if (birth_count_ > 1) - StringAppendF(output, "Births=%d ", birth_count_); - - DeathData::Write(output); -} - -void Aggregation::Clear() { - birth_count_ = 0; - birth_files_.clear(); - locations_.clear(); - birth_threads_.clear(); - DeathData::Clear(); - death_threads_.clear(); -} - -//------------------------------------------------------------------------------ -// Comparison object for sorting. - -Comparator::Comparator() - : selector_(NIL), - tiebreaker_(NULL), - combined_selectors_(0), - use_tiebreaker_for_sort_only_(false) {} - -void Comparator::Clear() { - if (tiebreaker_) { - tiebreaker_->Clear(); - delete tiebreaker_; - tiebreaker_ = NULL; - } - use_tiebreaker_for_sort_only_ = false; - selector_ = NIL; -} - -void Comparator::Sort(DataCollector::Collection* collection) const { - std::sort(collection->begin(), collection->end(), *this); -} - - -bool Comparator::operator()(const Snapshot& left, - const Snapshot& right) const { - switch (selector_) { - case BIRTH_THREAD: - if (left.birth_thread() != right.birth_thread() && - left.birth_thread()->ThreadName() != - right.birth_thread()->ThreadName()) - return left.birth_thread()->ThreadName() < - right.birth_thread()->ThreadName(); - break; - - case DEATH_THREAD: - if (left.death_thread() != right.death_thread() && - left.DeathThreadName() != - right.DeathThreadName()) { - if (!left.death_thread()) - return true; - if (!right.death_thread()) - return false; - return left.DeathThreadName() < - right.DeathThreadName(); - } - break; - - case BIRTH_FILE: - if (left.location().file_name() != right.location().file_name()) { - int comp = strcmp(left.location().file_name(), - right.location().file_name()); - if (comp) - return 0 > comp; - } - break; - - case BIRTH_FUNCTION: - if (left.location().function_name() != right.location().function_name()) { - int comp = strcmp(left.location().function_name(), - right.location().function_name()); - if (comp) - return 0 > comp; - } - break; - - case BIRTH_LINE: - if (left.location().line_number() != right.location().line_number()) - return left.location().line_number() < - right.location().line_number(); - break; - - case COUNT: - if (left.count() != right.count()) - return left.count() > right.count(); // Sort large at front of vector. - break; - - case AVERAGE_DURATION: - if (left.AverageMsDuration() != right.AverageMsDuration()) - return left.AverageMsDuration() > right.AverageMsDuration(); - break; - - default: - break; - } - if (tiebreaker_) - return tiebreaker_->operator()(left, right); - return false; -} - -bool Comparator::Equivalent(const Snapshot& left, - const Snapshot& right) const { - switch (selector_) { - case BIRTH_THREAD: - if (left.birth_thread() != right.birth_thread() && - left.birth_thread()->ThreadName() != - right.birth_thread()->ThreadName()) - return false; - break; - - case DEATH_THREAD: - if (left.death_thread() != right.death_thread() && - left.DeathThreadName() != right.DeathThreadName()) - return false; - break; - - case BIRTH_FILE: - if (left.location().file_name() != right.location().file_name()) { - int comp = strcmp(left.location().file_name(), - right.location().file_name()); - if (comp) - return false; - } - break; - - case BIRTH_FUNCTION: - if (left.location().function_name() != right.location().function_name()) { - int comp = strcmp(left.location().function_name(), - right.location().function_name()); - if (comp) - return false; - } - break; - - case COUNT: - if (left.count() != right.count()) - return false; - break; - - case AVERAGE_DURATION: - if (left.life_duration() != right.life_duration()) - return false; - break; - - default: - break; - } - if (tiebreaker_ && !use_tiebreaker_for_sort_only_) - return tiebreaker_->Equivalent(left, right); - return true; -} - -bool Comparator::Acceptable(const Snapshot& sample) const { - if (required_.size()) { - switch (selector_) { - case BIRTH_THREAD: - if (sample.birth_thread()->ThreadName().find(required_) == - std::string::npos) - return false; - break; - - case DEATH_THREAD: - if (sample.DeathThreadName().find(required_) == std::string::npos) - return false; - break; - - case BIRTH_FILE: - if (!strstr(sample.location().file_name(), required_.c_str())) - return false; - break; - - case BIRTH_FUNCTION: - if (!strstr(sample.location().function_name(), required_.c_str())) - return false; - break; - - default: - break; - } - } - if (tiebreaker_ && !use_tiebreaker_for_sort_only_) - return tiebreaker_->Acceptable(sample); - return true; -} - -void Comparator::SetTiebreaker(Selector selector, const std::string required) { - if (selector == selector_ || NIL == selector) - return; - combined_selectors_ |= selector; - if (NIL == selector_) { - selector_ = selector; - if (required.size()) - required_ = required; - return; - } - if (tiebreaker_) { - if (use_tiebreaker_for_sort_only_) { - Comparator* temp = new Comparator; - temp->tiebreaker_ = tiebreaker_; - tiebreaker_ = temp; - } - } else { - tiebreaker_ = new Comparator; - DCHECK(!use_tiebreaker_for_sort_only_); - } - tiebreaker_->SetTiebreaker(selector, required); -} - -bool Comparator::IsGroupedBy(Selector selector) const { - return 0 != (selector & combined_selectors_); -} - -void Comparator::SetSubgroupTiebreaker(Selector selector) { - if (selector == selector_ || NIL == selector) - return; - if (!tiebreaker_) { - use_tiebreaker_for_sort_only_ = true; - tiebreaker_ = new Comparator; - tiebreaker_->SetTiebreaker(selector, ""); - } else { - tiebreaker_->SetSubgroupTiebreaker(selector); - } -} - -bool Comparator::WriteSortGrouping(const Snapshot& sample, - std::string* output) const { - bool wrote_data = false; - switch (selector_) { - case BIRTH_THREAD: - StringAppendF(output, "All new on %s ", - sample.birth_thread()->ThreadName().c_str()); - wrote_data = true; - break; - - case DEATH_THREAD: - if (sample.death_thread()) - StringAppendF(output, "All deleted on %s ", - sample.DeathThreadName().c_str()); - else - output->append("All still alive "); - wrote_data = true; - break; - - case BIRTH_FILE: - StringAppendF(output, "All born in %s ", - sample.location().file_name()); - break; - - case BIRTH_FUNCTION: - output->append("All born in "); - sample.location().WriteFunctionName(output); - output->push_back(' '); - break; - - default: - break; - } - if (tiebreaker_ && !use_tiebreaker_for_sort_only_) { - wrote_data |= tiebreaker_->WriteSortGrouping(sample, output); - } - return wrote_data; -} - -void Comparator::WriteSnapshot(const Snapshot& sample, - std::string* output) const { - sample.death_data().Write(output); - if (!(combined_selectors_ & BIRTH_THREAD) || - !(combined_selectors_ & DEATH_THREAD)) - StringAppendF(output, "%s->%s ", - (combined_selectors_ & BIRTH_THREAD) ? "*" : - sample.birth().birth_thread()->ThreadName().c_str(), - (combined_selectors_ & DEATH_THREAD) ? "*" : - sample.DeathThreadName().c_str()); - sample.birth().location().Write(!(combined_selectors_ & BIRTH_FILE), - !(combined_selectors_ & BIRTH_FUNCTION), - output); -} - -} // namespace tracked_objects
deleted file mode 100644 --- a/ipc/chromium/src/base/tracked_objects.h +++ /dev/null @@ -1,499 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACKED_OBJECTS_H_ -#define BASE_TRACKED_OBJECTS_H_ - -//------------------------------------------------------------------------------ -#include <map> -#include <string> -#include <vector> - -#include "base/lock.h" -#include "mozilla/StaticMutex.h" -#include "base/message_loop.h" -#include "base/thread_local_storage.h" -#include "base/tracked.h" - - -namespace tracked_objects { - -//------------------------------------------------------------------------------ -// For a specific thread, and a specific birth place, the collection of all -// death info (with tallies for each death thread, to prevent access conflicts). -class ThreadData; -class BirthOnThread { - public: - explicit BirthOnThread(const Location& location); - - const Location location() const { return location_; } - const ThreadData* birth_thread() const { return birth_thread_; } - - private: - // File/lineno of birth. This defines the essence of the type, as the context - // of the birth (construction) often tell what the item is for. This field - // is const, and hence safe to access from any thread. - const Location location_; - - // The thread that records births into this object. Only this thread is - // allowed to access birth_count_ (which changes over time). - const ThreadData* birth_thread_; // The thread this birth took place on. - - DISALLOW_COPY_AND_ASSIGN(BirthOnThread); -}; - -//------------------------------------------------------------------------------ -// A class for accumulating counts of births (without bothering with a map<>). - -class Births: public BirthOnThread { - public: - explicit Births(const Location& location); - - int birth_count() const { return birth_count_; } - - // When we have a birth we update the count for this BirhPLace. - void RecordBirth() { ++birth_count_; } - - // When a birthplace is changed (updated), we need to decrement the counter - // for the old instance. - void ForgetBirth() { --birth_count_; } // We corrected a birth place. - - private: - // The number of births on this thread for our location_. - int birth_count_; - - DISALLOW_COPY_AND_ASSIGN(Births); -}; - -//------------------------------------------------------------------------------ -// Basic info summarizing multiple destructions of an object with a single -// birthplace (fixed Location). Used both on specific threads, and also used -// in snapshots when integrating assembled data. - -class DeathData { - public: - // Default initializer. - DeathData() : count_(0), square_duration_(0) {} - - // When deaths have not yet taken place, and we gather data from all the - // threads, we create DeathData stats that tally the number of births without - // a corrosponding death. - explicit DeathData(int count) : count_(count), square_duration_(0) {} - - void RecordDeath(const base::TimeDelta& duration); - - // Metrics accessors. - int count() const { return count_; } - base::TimeDelta life_duration() const { return life_duration_; } - int64_t square_duration() const { return square_duration_; } - int AverageMsDuration() const; - double StandardDeviation() const; - - // Accumulate metrics from other into this. - void AddDeathData(const DeathData& other); - - // Simple print of internal state. - void Write(std::string* output) const; - - void Clear(); - - private: - int count_; // Number of destructions. - base::TimeDelta life_duration_; // Sum of all lifetime durations. - int64_t square_duration_; // Sum of squares in milliseconds. -}; - -//------------------------------------------------------------------------------ -// A temporary collection of data that can be sorted and summarized. It is -// gathered (carefully) from many threads. Instances are held in arrays and -// processed, filtered, and rendered. -// The source of this data was collected on many threads, and is asynchronously -// changing. The data in this instance is not asynchronously changing. - -class Snapshot { - public: - // When snapshotting a full life cycle set (birth-to-death), use this: - Snapshot(const BirthOnThread& birth_on_thread, const ThreadData& death_thread, - const DeathData& death_data); - - // When snapshotting a birth, with no death yet, use this: - Snapshot(const BirthOnThread& birth_on_thread, int count); - - - const ThreadData* birth_thread() const { return birth_->birth_thread(); } - const Location location() const { return birth_->location(); } - const BirthOnThread& birth() const { return *birth_; } - const ThreadData* death_thread() const {return death_thread_; } - const DeathData& death_data() const { return death_data_; } - const std::string DeathThreadName() const; - - int count() const { return death_data_.count(); } - base::TimeDelta life_duration() const { return death_data_.life_duration(); } - int64_t square_duration() const { return death_data_.square_duration(); } - int AverageMsDuration() const { return death_data_.AverageMsDuration(); } - - void Write(std::string* output) const; - - void Add(const Snapshot& other); - - private: - const BirthOnThread* birth_; // Includes Location and birth_thread. - const ThreadData* death_thread_; - DeathData death_data_; -}; -//------------------------------------------------------------------------------ -// DataCollector is a container class for Snapshot and BirthOnThread count -// items. It protects the gathering under locks, so that it could be called via -// Posttask on any threads, such as all the target threads in parallel. - -class DataCollector { - public: - typedef std::vector<Snapshot> Collection; - - // Construct with a list of how many threads should contribute. This helps us - // determine (in the async case) when we are done with all contributions. - DataCollector(); - - // Add all stats from the indicated thread into our arrays. This function is - // mutex protected, and *could* be called from any threads (although current - // implementation serialized calls to Append). - void Append(const ThreadData& thread_data); - - // After the accumulation phase, the following access is to process data. - Collection* collection(); - - // After collection of death data is complete, we can add entries for all the - // remaining living objects. - void AddListOfLivingObjects(); - - private: - // This instance may be provided to several threads to contribute data. The - // following counter tracks how many more threads will contribute. When it is - // zero, then all asynchronous contributions are complete, and locked access - // is no longer needed. - int count_of_contributing_threads_; - - // The array that we collect data into. - Collection collection_; - - // The total number of births recorded at each location for which we have not - // seen a death count. - typedef std::map<const BirthOnThread*, int> BirthCount; - BirthCount global_birth_count_; - - Lock accumulation_lock_; // Protects access during accumulation phase. - - DISALLOW_COPY_AND_ASSIGN(DataCollector); -}; - -//------------------------------------------------------------------------------ -// Aggregation contains summaries (totals and subtotals) of groups of Snapshot -// instances to provide printing of these collections on a single line. - -class Aggregation: public DeathData { - public: - Aggregation() : birth_count_(0) {} - - void AddDeathSnapshot(const Snapshot& snapshot); - void AddBirths(const Births& births); - void AddBirth(const BirthOnThread& birth); - void AddBirthPlace(const Location& location); - void Write(std::string* output) const; - void Clear(); - - private: - int birth_count_; - std::map<std::string, int> birth_files_; - std::map<Location, int> locations_; - std::map<const ThreadData*, int> birth_threads_; - DeathData death_data_; - std::map<const ThreadData*, int> death_threads_; - - DISALLOW_COPY_AND_ASSIGN(Aggregation); -}; - -//------------------------------------------------------------------------------ -// Comparator does the comparison of Snapshot instances. It is -// used to order the instances in a vector. It orders them into groups (for -// aggregation), and can also order instances within the groups (for detailed -// rendering of the instances). - -class Comparator { - public: - enum Selector { - NIL = 0, - BIRTH_THREAD = 1, - DEATH_THREAD = 2, - BIRTH_FILE = 4, - BIRTH_FUNCTION = 8, - BIRTH_LINE = 16, - COUNT = 32, - AVERAGE_DURATION = 64, - TOTAL_DURATION = 128 - }; - - explicit Comparator(); - - // Reset the comparator to a NIL selector. Reset() and recursively delete any - // tiebreaker_ entries. NOTE: We can't use a standard destructor, because - // the sort algorithm makes copies of this object, and then deletes them, - // which would cause problems (either we'd make expensive deep copies, or we'd - // do more thna one delete on a tiebreaker_. - void Clear(); - - // The less() operator for sorting the array via std::sort(). - bool operator()(const Snapshot& left, const Snapshot& right) const; - - void Sort(DataCollector::Collection* collection) const; - - // Check to see if the items are sort equivalents (should be aggregated). - bool Equivalent(const Snapshot& left, const Snapshot& right) const; - - // Check to see if all required fields are present in the given sample. - bool Acceptable(const Snapshot& sample) const; - - // A comparator can be refined by specifying what to do if the selected basis - // for comparison is insufficient to establish an ordering. This call adds - // the indicated attribute as the new "least significant" basis of comparison. - void SetTiebreaker(Selector selector, const std::string required); - - // Indicate if this instance is set up to sort by the given Selector, thereby - // putting that information in the SortGrouping, so it is not needed in each - // printed line. - bool IsGroupedBy(Selector selector) const; - - // Using the tiebreakers as set above, we mostly get an ordering, which - // equivalent groups. If those groups are displayed (rather than just being - // aggregated, then the following is used to order them (within the group). - void SetSubgroupTiebreaker(Selector selector); - - // Output a header line that can be used to indicated what items will be - // collected in the group. It lists all (potentially) tested attributes and - // their values (in the sample item). - bool WriteSortGrouping(const Snapshot& sample, std::string* output) const; - - // Output a sample, with SortGroup details not displayed. - void WriteSnapshot(const Snapshot& sample, std::string* output) const; - - private: - // The selector directs this instance to compare based on the specified - // members of the tested elements. - enum Selector selector_; - - // For filtering into acceptable and unacceptable snapshot instance, the - // following is required to be a substring of the selector_ field. - std::string required_; - - // If this instance can't decide on an ordering, we can consult a tie-breaker - // which may have a different basis of comparison. - Comparator* tiebreaker_; - - // We or together all the selectors we sort on (not counting sub-group - // selectors), so that we can tell if we've decided to group on any given - // criteria. - int combined_selectors_; - - // Some tiebreakrs are for subgroup ordering, and not for basic ordering (in - // preparation for aggregation). The subgroup tiebreakers are not consulted - // when deciding if two items are in equivalent groups. This flag tells us - // to ignore the tiebreaker when doing Equivalent() testing. - bool use_tiebreaker_for_sort_only_; -}; - - -//------------------------------------------------------------------------------ -// For each thread, we have a ThreadData that stores all tracking info generated -// on this thread. This prevents the need for locking as data accumulates. - -class ThreadData { - public: - typedef std::map<Location, Births*> BirthMap; - typedef std::map<const Births*, DeathData> DeathMap; - - ThreadData(); - - // Using Thread Local Store, find the current instance for collecting data. - // If an instance does not exist, construct one (and remember it for use on - // this thread. - // If shutdown has already started, and we don't yet have an instance, then - // return null. - static ThreadData* current(); - - // In this thread's data, find a place to record a new birth. - Births* FindLifetime(const Location& location); - - // Find a place to record a death on this thread. - void TallyADeath(const Births& lifetimes, const base::TimeDelta& duration); - - // (Thread safe) Get start of list of instances. - static ThreadData* first(); - // Iterate through the null terminated list of instances. - ThreadData* next() const { return next_; } - - MessageLoop* message_loop() const { return message_loop_; } - const std::string ThreadName() const; - - // Using our lock, make a copy of the specified maps. These calls may arrive - // from non-local threads. - void SnapshotBirthMap(BirthMap *output) const; - void SnapshotDeathMap(DeathMap *output) const; - - static void RunOnAllThreads(void (*Func)()); - - // Set internal status_ to either become ACTIVE, or later, to be SHUTDOWN, - // based on argument being true or false respectively. - // IF tracking is not compiled in, this function will return false. - static bool StartTracking(bool status); - static bool IsActive(); - -#ifdef OS_WIN - // WARNING: ONLY call this function when all MessageLoops are still intact for - // all registered threads. IF you call it later, you will crash. - // Note: You don't need to call it at all, and you can wait till you are - // single threaded (again) to do the cleanup via - // ShutdownSingleThreadedCleanup(). - // Start the teardown (shutdown) process in a multi-thread mode by disabling - // further additions to thread database on all threads. First it makes a - // local (locked) change to prevent any more threads from registering. Then - // it Posts a Task to all registered threads to be sure they are aware that no - // more accumulation can take place. - static void ShutdownMultiThreadTracking(); -#endif - - // WARNING: ONLY call this function when you are running single threaded - // (again) and all message loops and threads have terminated. Until that - // point some threads may still attempt to write into our data structures. - // Delete recursively all data structures, starting with the list of - // ThreadData instances. - static void ShutdownSingleThreadedCleanup(); - - private: - // Current allowable states of the tracking system. The states always - // proceed towards SHUTDOWN, and never go backwards. - enum Status { - UNINITIALIZED, - ACTIVE, - SHUTDOWN - }; - - // A class used to count down which is accessed by several threads. This is - // used to make sure RunOnAllThreads() actually runs a task on the expected - // count of threads. - class ThreadSafeDownCounter { - public: - // Constructor sets the count, once and for all. - explicit ThreadSafeDownCounter(size_t count); - - // Decrement the count, and return true if we hit zero. Also delete this - // instance automatically when we hit zero. - bool LastCaller(); - - private: - size_t remaining_count_; - Lock lock_; // protect access to remaining_count_. - }; - -#ifdef OS_WIN - // A Task class that runs a static method supplied, and checks to see if this - // is the last tasks instance (on last thread) that will run the method. - // IF this is the last run, then the supplied event is signalled. - class RunTheStatic : public Task { - public: - typedef void (*FunctionPointer)(); - RunTheStatic(FunctionPointer function, - HANDLE completion_handle, - ThreadSafeDownCounter* counter); - // Run the supplied static method, and optionally set the event. - void Run(); - - private: - FunctionPointer function_; - HANDLE completion_handle_; - // Make sure enough tasks are called before completion is signaled. - ThreadSafeDownCounter* counter_; - - DISALLOW_COPY_AND_ASSIGN(RunTheStatic); - }; -#endif - - // Each registered thread is called to set status_ to SHUTDOWN. - // This is done redundantly on every registered thread because it is not - // protected by a mutex. Running on all threads guarantees we get the - // notification into the memory cache of all possible threads. - static void ShutdownDisablingFurtherTracking(); - - // We use thread local store to identify which ThreadData to interact with. - static TLSSlot tls_index_ ; - - // Link to the most recently created instance (starts a null terminated list). - static ThreadData* first_; - // Protection for access to first_. - static mozilla::StaticMutex list_lock_; - - - // We set status_ to SHUTDOWN when we shut down the tracking service. This - // setting is redundantly established by all participating - // threads so that we are *guaranteed* (without locking) that all threads - // can "see" the status and avoid additional calls into the service. - static Status status_; - - // Link to next instance (null terminated list). Used to globally track all - // registered instances (corresponds to all registered threads where we keep - // data). - ThreadData* next_; - - // The message loop where tasks needing to access this instance's private data - // should be directed. Since some threads have no message loop, some - // instances have data that can't be (safely) modified externally. - MessageLoop* message_loop_; - - // A map used on each thread to keep track of Births on this thread. - // This map should only be accessed on the thread it was constructed on. - // When a snapshot is needed, this structure can be locked in place for the - // duration of the snapshotting activity. - BirthMap birth_map_; - - // Similar to birth_map_, this records informations about death of tracked - // instances (i.e., when a tracked instance was destroyed on this thread). - DeathMap death_map_; - - // Lock to protect *some* access to BirthMap and DeathMap. We only use - // locking protection when we are growing the maps, or using an iterator. We - // only do writes to members from this thread, so the updates of values are - // atomic. Folks can read from other threads, and get (via races) new or old - // data, but that is considered acceptable errors (mis-information). - Lock lock_; - - DISALLOW_COPY_AND_ASSIGN(ThreadData); -}; - - -//------------------------------------------------------------------------------ -// Provide simple way to to start global tracking, and to tear down tracking -// when done. Note that construction and destruction of this object must be -// done when running in single threaded mode (before spawning a lot of threads -// for construction, and after shutting down all the threads for destruction). - -class AutoTracking { - public: - AutoTracking() { ThreadData::StartTracking(true); } - - ~AutoTracking() { -#ifndef NDEBUG // Don't call these in a Release build: they just waste time. - // The following should ONLY be called when in single threaded mode. It is - // unsafe to do this cleanup if other threads are still active. - // It is also very unnecessary, so I'm only doing this in debug to satisfy - // purify (if we need to!). - ThreadData::ShutdownSingleThreadedCleanup(); -#endif - } - - private: - DISALLOW_COPY_AND_ASSIGN(AutoTracking); -}; - - -} // namespace tracked_objects - -#endif // BASE_TRACKED_OBJECTS_H_
--- a/ipc/chromium/src/base/waitable_event_watcher.h +++ b/ipc/chromium/src/base/waitable_event_watcher.h @@ -139,16 +139,16 @@ class WaitableEventWatcher // --------------------------------------------------------------------------- // Implementation of MessageLoop::DestructionObserver // --------------------------------------------------------------------------- void WillDestroyCurrentMessageLoop(); MessageLoop* message_loop_; RefPtr<Flag> cancel_flag_; AsyncWaiter* waiter_; - AsyncCallbackTask* callback_task_; + RefPtr<AsyncCallbackTask> callback_task_; RefPtr<WaitableEvent::WaitableEventKernel> kernel_; #endif }; } // namespace base #endif // BASE_WAITABLE_EVENT_WATCHER_H_
--- a/ipc/chromium/src/base/waitable_event_watcher_posix.cc +++ b/ipc/chromium/src/base/waitable_event_watcher_posix.cc @@ -54,28 +54,29 @@ class Flag final { }; // ----------------------------------------------------------------------------- // This is an asynchronous waiter which posts a task to a MessageLoop when // fired. An AsyncWaiter may only be in a single wait-list. // ----------------------------------------------------------------------------- class AsyncWaiter final : public WaitableEvent::Waiter { public: - AsyncWaiter(MessageLoop* message_loop, Task* task, Flag* flag) + AsyncWaiter(MessageLoop* message_loop, + already_AddRefed<mozilla::Runnable> task, Flag* flag) : message_loop_(message_loop), cb_task_(task), flag_(flag) { } bool Fire(WaitableEvent* event) { if (flag_->value()) { // If the callback has been canceled, we don't enqueue the task, we just // delete it instead. - delete cb_task_; + cb_task_ = nullptr; } else { - message_loop_->PostTask(FROM_HERE, cb_task_); + message_loop_->PostTask(cb_task_.forget()); } // We are removed from the wait-list by the WaitableEvent itself. It only // remains to delete ourselves. delete this; // We can always return true because an AsyncWaiter is never in two // different wait-lists at the same time. @@ -84,57 +85,57 @@ class AsyncWaiter final : public Waitabl // See StopWatching for discussion bool Compare(void* tag) { return tag == flag_.get(); } private: MessageLoop *const message_loop_; - Task *const cb_task_; + RefPtr<mozilla::Runnable> cb_task_; RefPtr<Flag> flag_; }; // ----------------------------------------------------------------------------- // For async waits we need to make a callback in a MessageLoop thread. We do // this by posting this task, which calls the delegate and keeps track of when // the event is canceled. // ----------------------------------------------------------------------------- -class AsyncCallbackTask : public Task { +class AsyncCallbackTask : public mozilla::Runnable { public: AsyncCallbackTask(Flag* flag, WaitableEventWatcher::Delegate* delegate, WaitableEvent* event) : flag_(flag), delegate_(delegate), event_(event) { } - void Run() { + NS_IMETHOD Run() override { // Runs in MessageLoop thread. if (!flag_->value()) { // This is to let the WaitableEventWatcher know that the event has occured // because it needs to be able to return NULL from GetWatchedObject flag_->Set(); delegate_->OnWaitableEventSignaled(event_); } + return NS_OK; // We are deleted by the MessageLoop } private: RefPtr<Flag> flag_; WaitableEventWatcher::Delegate *const delegate_; WaitableEvent *const event_; }; WaitableEventWatcher::WaitableEventWatcher() : event_(NULL), message_loop_(NULL), - cancel_flag_(NULL), - callback_task_(NULL) { + cancel_flag_(NULL) { } WaitableEventWatcher::~WaitableEventWatcher() { StopWatching(); } // ----------------------------------------------------------------------------- // The Handle is how the user cancels a wait. After deleting the Handle we @@ -167,26 +168,28 @@ bool WaitableEventWatcher::StartWatching AutoLock locked(kernel->lock_); if (kernel->signaled_) { if (!kernel->manual_reset_) kernel->signaled_ = false; // No hairpinning - we can't call the delegate directly here. We have to // enqueue a task on the MessageLoop as normal. - current_ml->PostTask(FROM_HERE, callback_task_); + RefPtr<AsyncCallbackTask> addrefedTask = callback_task_; + current_ml->PostTask(addrefedTask.forget()); return true; } message_loop_ = current_ml; current_ml->AddDestructionObserver(this); event_ = event; kernel_ = kernel; - waiter_ = new AsyncWaiter(current_ml, callback_task_, cancel_flag_); + RefPtr<AsyncCallbackTask> addrefedTask = callback_task_; + waiter_ = new AsyncWaiter(current_ml, addrefedTask.forget(), cancel_flag_); event->Enqueue(waiter_); return true; } void WaitableEventWatcher::StopWatching() { if (message_loop_) { message_loop_->RemoveDestructionObserver(this); @@ -234,17 +237,17 @@ void WaitableEventWatcher::StopWatching( // still exists. So if we find a waiter with the correct pointer value, and // which shares a Flag pointer, we have a real match. if (kernel_->Dequeue(waiter_, cancel_flag_.get())) { // Case 2: the waiter hasn't been signaled yet; it was still on the wait // list. We've removed it, thus we can delete it and the task (which cannot // have been enqueued with the MessageLoop because the waiter was never // signaled) delete waiter_; - delete callback_task_; + callback_task_ = nullptr; cancel_flag_ = NULL; return; } // Case 3: the waiter isn't on the wait-list, thus it was signaled. It may // not have run yet, so we set the flag to tell it not to bother enqueuing the // task on the MessageLoop, but to delete it instead. The Waiter deletes // itself once run.
--- a/ipc/chromium/src/base/win_util.cc +++ b/ipc/chromium/src/base/win_util.cc @@ -5,17 +5,16 @@ #include "base/win_util.h" #include <map> #include <sddl.h> #include "base/logging.h" #include "base/singleton.h" #include "base/string_util.h" -#include "base/tracked.h" namespace win_util { std::wstring FormatMessage(unsigned messageid) { wchar_t* string_buffer = NULL; unsigned string_length = ::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, messageid, 0,
--- a/ipc/chromium/src/base/win_util.h +++ b/ipc/chromium/src/base/win_util.h @@ -5,18 +5,16 @@ #ifndef BASE_WIN_UTIL_H__ #define BASE_WIN_UTIL_H__ #include <windows.h> #include <aclapi.h> #include <string> -#include "base/tracked.h" - namespace win_util { // Uses the last Win32 error to generate a human readable message string. std::wstring FormatLastWin32Error(); } // namespace win_util #endif // BASE_WIN_UTIL_H__
--- a/ipc/chromium/src/chrome/common/child_process_host.cc +++ b/ipc/chromium/src/chrome/common/child_process_host.cc @@ -22,26 +22,27 @@ typedef mozilla::ipc::BrowserProcessSubT using mozilla::ipc::FileDescriptor; namespace { typedef std::list<ChildProcessHost*> ChildProcessList; // The NotificationTask is used to notify about plugin process connection/ // disconnection. It is needed because the notifications in the // NotificationService must happen in the main thread. -class ChildNotificationTask : public Task { +class ChildNotificationTask : public mozilla::Runnable { public: ChildNotificationTask( NotificationType notification_type, ChildProcessInfo* info) : notification_type_(notification_type), info_(*info) { } - virtual void Run() { + NS_IMETHOD Run() { NotificationService::current()-> Notify(notification_type_, NotificationService::AllSources(), Details<ChildProcessInfo>(&info_)); + return NS_OK; } private: NotificationType notification_type_; ChildProcessInfo info_; }; } // namespace @@ -124,18 +125,18 @@ bool ChildProcessHost::Send(IPC::Message } void ChildProcessHost::Notify(NotificationType type) { MessageLoop* loop = ChromeThread::GetMessageLoop(ChromeThread::IO); if (!loop) loop = mozilla::ipc::ProcessChild::message_loop(); if (!loop) loop = MessageLoop::current(); - loop->PostTask( - FROM_HERE, new ChildNotificationTask(type, this)); + RefPtr<ChildNotificationTask> task = new ChildNotificationTask(type, this); + loop->PostTask(task.forget()); } void ChildProcessHost::OnWaitableEventSignaled(base::WaitableEvent *event) { #if defined(OS_WIN) HANDLE object = event->handle(); DCHECK(handle()); DCHECK_EQ(object, handle());
--- a/ipc/chromium/src/chrome/common/child_thread.cc +++ b/ipc/chromium/src/chrome/common/child_thread.cc @@ -28,25 +28,25 @@ ChildThread::~ChildThread() { #ifdef MOZ_NUWA_PROCESS #include "ipc/Nuwa.h" #endif bool ChildThread::Run() { bool r = StartWithOptions(options_); #ifdef MOZ_NUWA_PROCESS if (IsNuwaProcess()) { - message_loop()->PostTask(FROM_HERE, - NewRunnableFunction(&ChildThread::MarkThread)); + message_loop()->PostTask(NewRunnableFunction(&ChildThread::MarkThread)); } #endif return r; } void ChildThread::OnChannelError() { - owner_loop_->PostTask(FROM_HERE, new MessageLoop::QuitTask()); + RefPtr<mozilla::Runnable> task = new MessageLoop::QuitTask(); + owner_loop_->PostTask(task.forget()); } #ifdef MOZ_NUWA_PROCESS void ChildThread::MarkThread() { NuwaMarkCurrentThread(nullptr, nullptr); if (!NuwaCheckpointCurrentThread()) { NS_RUNTIMEABORT("Should not be here!"); } @@ -82,12 +82,13 @@ void ChildThread::Init() { void ChildThread::CleanUp() { // Need to destruct the SyncChannel to the browser before we go away because // it caches a pointer to this thread. channel_ = nullptr; } void ChildThread::OnProcessFinalRelease() { if (!check_with_browser_before_shutdown_) { - owner_loop_->PostTask(FROM_HERE, new MessageLoop::QuitTask()); + RefPtr<mozilla::Runnable> task = new MessageLoop::QuitTask(); + owner_loop_->PostTask(task.forget()); return; } }
--- a/ipc/chromium/src/chrome/common/ipc_channel_win.cc +++ b/ipc/chromium/src/chrome/common/ipc_channel_win.cc @@ -260,17 +260,17 @@ bool Channel::ChannelImpl::Connect() { // Check to see if there is a client connected to our pipe... if (waiting_connect_) ProcessConnection(); if (!input_state_.is_pending) { // Complete setup asynchronously. By not setting input_state_.is_pending // to true, we indicate to OnIOCompleted that this is the special // initialization signal. - MessageLoopForIO::current()->PostTask(FROM_HERE, factory_.NewRunnableMethod( + MessageLoopForIO::current()->PostTask(factory_.NewRunnableMethod( &Channel::ChannelImpl::OnIOCompleted, &input_state_.context, 0, 0)); } if (!waiting_connect_) ProcessOutgoingMessages(NULL, 0); return true; }
--- a/ipc/chromium/src/chrome/common/process_watcher_posix_sigchld.cc +++ b/ipc/chromium/src/chrome/common/process_watcher_posix_sigchld.cc @@ -72,35 +72,37 @@ protected: private: DISALLOW_EVIL_CONSTRUCTORS(ChildReaper); }; // Fear the reaper class ChildGrimReaper : public ChildReaper, - public Task + public mozilla::Runnable { public: explicit ChildGrimReaper(pid_t process) : ChildReaper(process) { } virtual ~ChildGrimReaper() { if (process_) KillProcess(); } // @override - virtual void Run() + NS_IMETHOD Run() { // we may have already been signaled by the time this runs if (process_) KillProcess(); + + return NS_OK; } private: void KillProcess() { DCHECK(process_); if (IsProcessDead(process_)) { @@ -195,21 +197,21 @@ ProcessWatcher::EnsureProcessTerminated( DCHECK(process != base::GetCurrentProcId()); DCHECK(process > 0); if (IsProcessDead(process)) return; MessageLoopForIO* loop = MessageLoopForIO::current(); if (force) { - ChildGrimReaper* reaper = new ChildGrimReaper(process); + RefPtr<ChildGrimReaper> reaper = new ChildGrimReaper(process); loop->CatchSignal(SIGCHLD, reaper, reaper); // |loop| takes ownership of |reaper| - loop->PostDelayedTask(FROM_HERE, reaper, kMaxWaitMs); + loop->PostDelayedTask(reaper.forget(), kMaxWaitMs); } else { ChildLaxReaper* reaper = new ChildLaxReaper(process); loop->CatchSignal(SIGCHLD, reaper, reaper); // |reaper| destroys itself after destruction notification loop->AddDestructionObserver(reaper); } }
--- a/ipc/chromium/src/chrome/common/process_watcher_win.cc +++ b/ipc/chromium/src/chrome/common/process_watcher_win.cc @@ -9,34 +9,36 @@ #include "base/sys_info.h" #include "chrome/common/result_codes.h" // Maximum amount of time (in milliseconds) to wait for the process to exit. static const int kWaitInterval = 2000; namespace { -class TimerExpiredTask : public Task, public base::ObjectWatcher::Delegate { +class TimerExpiredTask : public mozilla::Runnable, + public base::ObjectWatcher::Delegate { public: explicit TimerExpiredTask(base::ProcessHandle process) : process_(process) { watcher_.StartWatching(process_, this); } virtual ~TimerExpiredTask() { if (process_) { KillProcess(); DCHECK(!process_) << "Make sure to close the handle."; } } // Task --------------------------------------------------------------------- - virtual void Run() { + NS_IMETHOD Run() override { if (process_) KillProcess(); + return NS_OK; } // MessageLoop::Watcher ----------------------------------------------------- virtual void OnObjectSignaled(HANDLE object) { // When we're called from KillProcess, the ObjectWatcher may still be // watching. the process handle, so make sure it has stopped. watcher_.StopWatching(); @@ -80,12 +82,13 @@ void ProcessWatcher::EnsureProcessTermin } // If already signaled, then we are done! if (WaitForSingleObject(process, 0) == WAIT_OBJECT_0) { base::CloseProcessHandle(process); return; } - MessageLoop::current()->PostDelayedTask(FROM_HERE, - new TimerExpiredTask(process), + RefPtr<mozilla::Runnable> task = new TimerExpiredTask(process); + + MessageLoop::current()->PostDelayedTask(task.forget(), kWaitInterval); }
--- a/ipc/glue/BackgroundImpl.cpp +++ b/ipc/glue/BackgroundImpl.cpp @@ -443,18 +443,20 @@ private: } static void DispatchFailureCallback(nsIEventTarget* aEventTarget); // This class is reference counted. ~ChildImpl() { - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, - new DeleteTask<Transport>(GetTransport())); + RefPtr<DeleteTask<Transport>> task = + new DeleteTask<Transport>(GetTransport()); + XRE_GetIOMessageLoop()->PostTask(task.forget()); + AssertActorDestroyed(); } void SetBoundThread() { THREADSAFETY_ASSERT(!mBoundThread); @@ -1282,18 +1284,18 @@ ParentImpl::MainThreadActorDestroy() AssertIsInMainProcess(); AssertIsOnMainThread(); MOZ_ASSERT_IF(mIsOtherProcessActor, mContent); MOZ_ASSERT_IF(!mIsOtherProcessActor, !mContent); MOZ_ASSERT_IF(mIsOtherProcessActor, mTransport); MOZ_ASSERT_IF(!mIsOtherProcessActor, !mTransport); if (mTransport) { - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, - new DeleteTask<Transport>(mTransport)); + RefPtr<DeleteTask<Transport>> task = new DeleteTask<Transport>(mTransport); + XRE_GetIOMessageLoop()->PostTask(task.forget()); mTransport = nullptr; } mContent = nullptr; MOZ_ASSERT(sLiveActorCount); sLiveActorCount--;
--- a/ipc/glue/GeckoChildProcessHost.cpp +++ b/ipc/glue/GeckoChildProcessHost.cpp @@ -346,33 +346,31 @@ void GeckoChildProcessHost::InitWindowsG bool GeckoChildProcessHost::SyncLaunch(std::vector<std::string> aExtraOpts, int aTimeoutMs, base::ProcessArchitecture arch) { PrepareLaunch(); MessageLoop* ioLoop = XRE_GetIOMessageLoop(); NS_ASSERTION(MessageLoop::current() != ioLoop, "sync launch from the IO thread NYI"); - ioLoop->PostTask(FROM_HERE, - NewRunnableMethod(this, + ioLoop->PostTask(NewRunnableMethod(this, &GeckoChildProcessHost::RunPerformAsyncLaunch, aExtraOpts, arch)); return WaitUntilConnected(aTimeoutMs); } bool GeckoChildProcessHost::AsyncLaunch(std::vector<std::string> aExtraOpts, base::ProcessArchitecture arch) { PrepareLaunch(); MessageLoop* ioLoop = XRE_GetIOMessageLoop(); - ioLoop->PostTask(FROM_HERE, - NewRunnableMethod(this, + ioLoop->PostTask(NewRunnableMethod(this, &GeckoChildProcessHost::RunPerformAsyncLaunch, aExtraOpts, arch)); // This may look like the sync launch wait, but we only delay as // long as it takes to create the channel. MonitorAutoLock lock(mMonitor); while (mProcessState < CHANNEL_INITIALIZED) { lock.Wait(); @@ -420,18 +418,17 @@ GeckoChildProcessHost::WaitUntilConnecte } bool GeckoChildProcessHost::LaunchAndWaitForProcessHandle(StringVector aExtraOpts) { PrepareLaunch(); MessageLoop* ioLoop = XRE_GetIOMessageLoop(); - ioLoop->PostTask(FROM_HERE, - NewRunnableMethod(this, + ioLoop->PostTask(NewRunnableMethod(this, &GeckoChildProcessHost::RunPerformAsyncLaunch, aExtraOpts, base::GetCurrentProcessArchitecture())); MonitorAutoLock lock(mMonitor); while (mProcessState < PROCESS_CREATED) { lock.Wait(); } MOZ_ASSERT(mProcessState == PROCESS_ERROR || mChildProcessHandle); @@ -475,29 +472,27 @@ GeckoChildProcessHost::SetAlreadyDead() } namespace { void DelayedDeleteSubprocess(GeckoChildProcessHost* aSubprocess) { XRE_GetIOMessageLoop() - ->PostTask(FROM_HERE, - new DeleteTask<GeckoChildProcessHost>(aSubprocess)); + ->PostTask(mozilla::MakeAndAddRef<DeleteTask<GeckoChildProcessHost>>(aSubprocess)); } } void GeckoChildProcessHost::DissociateActor() { if (!--mAssociatedActors) { MessageLoop::current()-> - PostTask(FROM_HERE, - NewRunnableFunction(DelayedDeleteSubprocess, this)); + PostTask(NewRunnableFunction(DelayedDeleteSubprocess, this)); } } int32_t GeckoChildProcessHost::mChildCounter = 0; void GeckoChildProcessHost::SetChildLogName(const char* varName, const char* origLogName) {
--- a/ipc/glue/MessageChannel.cpp +++ b/ipc/glue/MessageChannel.cpp @@ -689,17 +689,16 @@ MessageChannel::Open(MessageChannel *aTa case UnknownSide: break; } mMonitor = new RefCountedMonitor(); MonitorAutoLock lock(*mMonitor); mChannelState = ChannelOpening; aTargetLoop->PostTask( - FROM_HERE, NewRunnableMethod(aTargetChan, &MessageChannel::OnOpenAsSlave, this, oppSide)); while (ChannelOpening == mChannelState) mMonitor->Wait(); MOZ_RELEASE_ASSERT(ChannelConnected == mChannelState, "not connected when awoken"); return (ChannelConnected == mChannelState); } @@ -978,17 +977,18 @@ MessageChannel::OnMessageReceivedFromLin if (shouldWakeUp) { NotifyWorkerThread(); } if (shouldPostTask) { if (!compress) { // If we compressed away the previous message, we'll re-use // its pending task. - mWorkerLoop->PostTask(FROM_HERE, new DequeueTask(mDequeueOneTask)); + RefPtr<DequeueTask> task = new DequeueTask(mDequeueOneTask); + mWorkerLoop->PostTask(task.forget()); } } } void MessageChannel::PeekMessages(mozilla::function<bool(const Message& aMsg)> aInvoke) { MonitorAutoLock lock(*mMonitor); @@ -1800,24 +1800,26 @@ void MessageChannel::EnqueuePendingMessages() { AssertWorkerThread(); mMonitor->AssertCurrentThreadOwns(); MaybeUndeferIncall(); for (size_t i = 0; i < mDeferred.size(); ++i) { - mWorkerLoop->PostTask(FROM_HERE, new DequeueTask(mDequeueOneTask)); + RefPtr<DequeueTask> task = new DequeueTask(mDequeueOneTask); + mWorkerLoop->PostTask(task.forget()); } // XXX performance tuning knob: could process all or k pending // messages here, rather than enqueuing for later processing for (size_t i = 0; i < mPending.size(); ++i) { - mWorkerLoop->PostTask(FROM_HERE, new DequeueTask(mDequeueOneTask)); + RefPtr<DequeueTask> task = new DequeueTask(mDequeueOneTask); + mWorkerLoop->PostTask(task.forget()); } } static inline bool IsTimeoutExpired(PRIntervalTime aStart, PRIntervalTime aTimeout) { return (aTimeout != PR_INTERVAL_NO_TIMEOUT) && (aTimeout <= (PR_IntervalNow() - aStart)); @@ -1915,17 +1917,18 @@ MessageChannel::SetReplyTimeoutMs(int32_ } void MessageChannel::OnChannelConnected(int32_t peer_id) { MOZ_RELEASE_ASSERT(!mPeerPidSet); mPeerPidSet = true; mPeerPid = peer_id; - mWorkerLoop->PostTask(FROM_HERE, new DequeueTask(mOnChannelConnectedTask)); + RefPtr<DequeueTask> task = new DequeueTask(mOnChannelConnectedTask); + mWorkerLoop->PostTask(task.forget()); } void MessageChannel::DispatchOnChannelConnected() { AssertWorkerThread(); MOZ_RELEASE_ASSERT(mPeerPidSet); if (mListener) @@ -2084,18 +2087,19 @@ MessageChannel::OnNotifyMaybeChannelErro { MonitorAutoLock lock(*mMonitor); // nothing to do here } if (IsOnCxxStack()) { mChannelErrorTask = NewRunnableMethod(this, &MessageChannel::OnNotifyMaybeChannelError); + RefPtr<Runnable> task = mChannelErrorTask; // 10 ms delay is completely arbitrary - mWorkerLoop->PostDelayedTask(FROM_HERE, mChannelErrorTask, 10); + mWorkerLoop->PostDelayedTask(task.forget(), 10); return; } NotifyMaybeChannelError(); } void MessageChannel::PostErrorNotifyTask() @@ -2103,17 +2107,18 @@ MessageChannel::PostErrorNotifyTask() mMonitor->AssertCurrentThreadOwns(); if (mChannelErrorTask) return; // This must be the last code that runs on this thread! mChannelErrorTask = NewRunnableMethod(this, &MessageChannel::OnNotifyMaybeChannelError); - mWorkerLoop->PostTask(FROM_HERE, mChannelErrorTask); + RefPtr<Runnable> task = mChannelErrorTask; + mWorkerLoop->PostTask(task.forget()); } // Special async message. class GoodbyeMessage : public IPC::Message { public: GoodbyeMessage() : IPC::Message(MSG_ROUTING_NONE, GOODBYE_MESSAGE_TYPE, PRIORITY_NORMAL) @@ -2298,17 +2303,18 @@ MessageChannel::EndTimeout() mTimedOutMessageSeqno = 0; mTimedOutMessagePriority = 0; for (size_t i = 0; i < mPending.size(); i++) { // There may be messages in the queue that we expected to process from // OnMaybeDequeueOne. But during the timeout, that function will skip // some messages. Now they're ready to be processed, so we enqueue more // tasks. - mWorkerLoop->PostTask(FROM_HERE, new DequeueTask(mDequeueOneTask)); + RefPtr<DequeueTask> task = new DequeueTask(mDequeueOneTask); + mWorkerLoop->PostTask(task.forget()); } } void MessageChannel::CancelTransaction(int transaction) { mMonitor->AssertCurrentThreadOwns();
--- a/ipc/glue/MessageChannel.h +++ b/ipc/glue/MessageChannel.h @@ -457,58 +457,62 @@ class MessageChannel : HasResultCodes "on worker thread but should not be!"); } private: typedef IPC::Message::msgid_t msgid_t; typedef std::deque<Message> MessageQueue; typedef std::map<size_t, Message> MessageMap; + // XXXkhuey this can almost certainly die. // All dequeuing tasks require a single point of cancellation, // which is handled via a reference-counted task. class RefCountedTask { public: - explicit RefCountedTask(CancelableTask* aTask) + explicit RefCountedTask(already_AddRefed<CancelableRunnable> aTask) : mTask(aTask) { } private: - ~RefCountedTask() { delete mTask; } + ~RefCountedTask() { } public: void Run() { mTask->Run(); } void Cancel() { mTask->Cancel(); } NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RefCountedTask) private: - CancelableTask* mTask; + RefPtr<CancelableRunnable> mTask; }; // Wrap an existing task which can be cancelled at any time // without the wrapper's knowledge. - class DequeueTask : public Task + class DequeueTask : public Runnable { public: explicit DequeueTask(RefCountedTask* aTask) : mTask(aTask) { } - void Run() override { mTask->Run(); } + NS_IMETHOD Run() override { + mTask->Run(); + return NS_OK; + } private: RefPtr<RefCountedTask> mTask; }; private: mozilla::WeakPtr<MessageListener> mListener; ChannelState mChannelState; RefPtr<RefCountedMonitor> mMonitor; Side mSide; MessageLink* mLink; MessageLoop* mWorkerLoop; // thread where work is done - CancelableTask* mChannelErrorTask; // NotifyMaybeChannelError runnable + RefPtr<CancelableRunnable> mChannelErrorTask; // NotifyMaybeChannelError runnable // id() of mWorkerLoop. This persists even after mWorkerLoop is cleared // during channel shutdown. int mWorkerLoopID; // A task encapsulating dequeuing one pending message. RefPtr<RefCountedTask> mDequeueOneTask;
--- a/ipc/glue/MessageLink.cpp +++ b/ipc/glue/MessageLink.cpp @@ -127,24 +127,22 @@ ProcessLink::Open(mozilla::ipc::Transpor { MonitorAutoLock lock(*mChan->mMonitor); if (needOpen) { // Transport::Connect() has not been called. Call it so // we start polling our pipe and processing outgoing // messages. mIOLoop->PostTask( - FROM_HERE, NewRunnableMethod(this, &ProcessLink::OnChannelOpened)); } else { // Transport::Connect() has already been called. Take // over the channel from the previous listener and process // any queued messages. mIOLoop->PostTask( - FROM_HERE, NewRunnableMethod(this, &ProcessLink::OnTakeConnectedChannel)); } #ifdef MOZ_NUWA_PROCESS if (IsNuwaProcess() && NS_IsMainThread() && Preferences::GetBool("dom.ipc.processPrelaunch.testMode")) { // The pref value is turned on in a deadlock test against the Nuwa // process. The sleep here makes it easy to trigger the deadlock @@ -163,17 +161,16 @@ ProcessLink::Open(mozilla::ipc::Transpor void ProcessLink::EchoMessage(Message *msg) { mChan->AssertWorkerThread(); mChan->mMonitor->AssertCurrentThreadOwns(); mIOLoop->PostTask( - FROM_HERE, NewRunnableMethod(this, &ProcessLink::OnEchoMessage, msg)); // OnEchoMessage takes ownership of |msg| } void ProcessLink::SendMessage(Message *msg) { mChan->AssertWorkerThread(); @@ -211,28 +208,26 @@ ProcessLink::SendMessage(Message *msg) jsstack ? jsstack : "<no JS stack>"); JS_smprintf_free(jsstack); MOZ_CRASH(); } #endif #endif mIOLoop->PostTask( - FROM_HERE, NewRunnableMethod(mTransport, &Transport::Send, msg)); } void ProcessLink::SendClose() { mChan->AssertWorkerThread(); mChan->mMonitor->AssertCurrentThreadOwns(); - mIOLoop->PostTask( - FROM_HERE, NewRunnableMethod(this, &ProcessLink::OnCloseChannel)); + mIOLoop->PostTask(NewRunnableMethod(this, &ProcessLink::OnCloseChannel)); } ThreadLink::ThreadLink(MessageChannel *aChan, MessageChannel *aTargetChan) : MessageLink(aChan), mTargetChan(aTargetChan) { }
--- a/toolkit/xre/nsEmbedFunctions.cpp +++ b/toolkit/xre/nsEmbedFunctions.cpp @@ -787,17 +787,18 @@ XRE_RunAppShell() // event-loop system, we compromise here by processing any tasks // that might have been enqueued on MessagePump, *before* // MessagePump::ScheduleWork was able to successfully // DispatchToMainThread(). MessageLoop* loop = MessageLoop::current(); bool couldNest = loop->NestableTasksAllowed(); loop->SetNestableTasksAllowed(true); - loop->PostTask(FROM_HERE, new MessageLoop::QuitTask()); + RefPtr<Runnable> task = new MessageLoop::QuitTask(); + loop->PostTask(task.forget()); loop->Run(); loop->SetNestableTasksAllowed(couldNest); } #endif // XP_MACOSX return appShell->Run(); }
--- a/widget/android/AndroidBridge.cpp +++ b/widget/android/AndroidBridge.cpp @@ -2096,22 +2096,22 @@ AndroidBridge::ProgressiveUpdateCallback } class AndroidBridge::DelayedTask { using TimeStamp = mozilla::TimeStamp; using TimeDuration = mozilla::TimeDuration; public: - DelayedTask(Task* aTask) + DelayedTask(already_AddRefed<Runnable> aTask) : mTask(aTask) , mRunTime() // Null timestamp representing no delay. {} - DelayedTask(Task* aTask, int aDelayMs) + DelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs) : mTask(aTask) , mRunTime(TimeStamp::Now() + TimeDuration::FromMilliseconds(aDelayMs)) {} bool IsEarlierThan(const DelayedTask& aOther) const { if (mRunTime) { return aOther.mRunTime ? mRunTime < aOther.mRunTime : false; @@ -2124,35 +2124,35 @@ public: int64_t MillisecondsToRunTime() const { if (mRunTime) { return int64_t((mRunTime - TimeStamp::Now()).ToMilliseconds()); } return 0; } - UniquePtr<Task>&& GetTask() + already_AddRefed<Runnable> TakeTask() { - return static_cast<UniquePtr<Task>&&>(mTask); + return mTask.forget(); } private: - UniquePtr<Task> mTask; + RefPtr<Runnable> mTask; const TimeStamp mRunTime; }; void -AndroidBridge::PostTaskToUiThread(Task* aTask, int aDelayMs) +AndroidBridge::PostTaskToUiThread(already_AddRefed<Runnable> aTask, int aDelayMs) { // add the new task into the mUiTaskQueue, sorted with // the earliest task first in the queue size_t i; - DelayedTask newTask(aDelayMs ? DelayedTask(aTask, aDelayMs) - : DelayedTask(aTask)); + DelayedTask newTask(aDelayMs ? DelayedTask(mozilla::Move(aTask), aDelayMs) + : DelayedTask(mozilla::Move(aTask))); { MutexAutoLock lock(mUiTaskQueueLock); for (i = 0; i < mUiTaskQueue.Length(); i++) { if (newTask.IsEarlierThan(mUiTaskQueue[i])) { mUiTaskQueue.InsertElementAt(i, mozilla::Move(newTask)); break; @@ -2183,17 +2183,17 @@ AndroidBridge::RunDelayedUiThreadTasks() if (timeLeft > 0) { // this task (and therefore all remaining tasks) // have not yet reached their runtime. return the // time left until we should be called again return timeLeft; } // Retrieve task before unlocking/running. - const UniquePtr<Task> nextTask(mUiTaskQueue[0].GetTask()); + RefPtr<Runnable> nextTask(mUiTaskQueue[0].TakeTask()); mUiTaskQueue.RemoveElementAt(0); // Unlock to allow posting new tasks reentrantly. MutexAutoUnlock unlock(mUiTaskQueueLock); nextTask->Run(); } return -1; }
--- a/widget/android/AndroidBridge.h +++ b/widget/android/AndroidBridge.h @@ -34,26 +34,27 @@ #include "mozilla/jni/Utils.h" #include "nsIObserver.h" // Some debug #defines // #define DEBUG_ANDROID_EVENTS // #define DEBUG_ANDROID_WIDGET class nsIObserver; -class Task; namespace base { class Thread; } // end namespace base typedef void* EGLSurface; namespace mozilla { +class Runnable; + namespace hal { class BatteryInformation; class NetworkInformation; } // namespace hal namespace dom { namespace mobilemessage { class SmsFilterData; @@ -413,17 +414,17 @@ protected: void (* Region_set)(void* region, void* rect); private: class DelayedTask; nsTArray<DelayedTask> mUiTaskQueue; mozilla::Mutex mUiTaskQueueLock; public: - void PostTaskToUiThread(Task* aTask, int aDelayMs); + void PostTaskToUiThread(already_AddRefed<Runnable> aTask, int aDelayMs); int64_t RunDelayedUiThreadTasks(); void* GetPresentationWindow(); void SetPresentationWindow(void* aPresentationWindow); EGLSurface GetPresentationSurface(); void SetPresentationSurface(EGLSurface aPresentationSurface); private:
--- a/widget/android/AndroidContentController.cpp +++ b/widget/android/AndroidContentController.cpp @@ -82,19 +82,19 @@ AndroidContentController::HandleSingleTa NS_ConvertASCIItoUTF16(data).get()); }); } ChromeProcessController::HandleSingleTap(aPoint, aModifiers, aGuid); } void -AndroidContentController::PostDelayedTask(Task* aTask, int aDelayMs) +AndroidContentController::PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs) { - AndroidBridge::Bridge()->PostTaskToUiThread(aTask, aDelayMs); + AndroidBridge::Bridge()->PostTaskToUiThread(Move(aTask), aDelayMs); } void AndroidContentController::UpdateOverscrollVelocity(const float aX, const float aY) { if (mAndroidWindow) { mAndroidWindow->UpdateOverscrollVelocity(aX, aY); } }
--- a/widget/android/AndroidContentController.h +++ b/widget/android/AndroidContentController.h @@ -32,17 +32,17 @@ public: , mAndroidWindow(aWindow) {} // ChromeProcessController methods virtual void Destroy() override; void HandleSingleTap(const CSSPoint& aPoint, Modifiers aModifiers, const ScrollableLayerGuid& aGuid) override; - void PostDelayedTask(Task* aTask, int aDelayMs) override; + void PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs) override; void UpdateOverscrollVelocity(const float aX, const float aY) override; void UpdateOverscrollOffset(const float aX, const float aY) override; void SetScrollingRootContent(const bool isRootContent) override; void NotifyAPZStateChange(const ScrollableLayerGuid& aGuid, APZStateChange aChange, int aArg) override; static void NotifyDefaultPrevented(mozilla::layers::APZCTreeManager* aManager,
--- a/widget/android/nsAppShell.cpp +++ b/widget/android/nsAppShell.cpp @@ -686,17 +686,17 @@ nsAppShell::LegacyGeckoEvent::Run() case AndroidGeckoEvent::THUMBNAIL: { if (!nsAppShell::Get()->mBrowserApp) break; int32_t tabId = curEvent->MetaState(); const nsTArray<nsIntPoint>& points = curEvent->Points(); RefCountedJavaObject* buffer = curEvent->ByteBuffer(); RefPtr<ThumbnailRunnable> sr = new ThumbnailRunnable(nsAppShell::Get()->mBrowserApp, tabId, points, buffer); - MessageLoop::current()->PostIdleTask(FROM_HERE, NewRunnableMethod(sr.get(), &ThumbnailRunnable::Run)); + MessageLoop::current()->PostIdleTask(NewRunnableMethod(sr.get(), &ThumbnailRunnable::Run)); break; } case AndroidGeckoEvent::ZOOMEDVIEW: { if (!nsAppShell::Get()->mBrowserApp) break; int32_t tabId = curEvent->MetaState(); const nsTArray<nsIntPoint>& points = curEvent->Points();
--- a/widget/nsBaseWidget.cpp +++ b/widget/nsBaseWidget.cpp @@ -1099,70 +1099,70 @@ nsBaseWidget::ProcessUntransformedAPZEve } else if (WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent()) { mAPZEventState->ProcessMouseEvent(*mouseEvent, aGuid, aInputBlockId); } } return status; } -class DispatchWheelEventOnMainThread : public Task +class DispatchWheelEventOnMainThread : public Runnable { public: DispatchWheelEventOnMainThread(const ScrollWheelInput& aWheelInput, nsBaseWidget* aWidget, nsEventStatus aAPZResult, uint64_t aInputBlockId, ScrollableLayerGuid aGuid) : mWheelInput(aWheelInput) , mWidget(aWidget) , mAPZResult(aAPZResult) , mInputBlockId(aInputBlockId) , mGuid(aGuid) { } - void Run() + NS_IMETHOD Run() override { WidgetWheelEvent wheelEvent = mWheelInput.ToWidgetWheelEvent(mWidget); mWidget->ProcessUntransformedAPZEvent(&wheelEvent, mGuid, mInputBlockId, mAPZResult); - return; + return NS_OK; } private: ScrollWheelInput mWheelInput; nsBaseWidget* mWidget; nsEventStatus mAPZResult; uint64_t mInputBlockId; ScrollableLayerGuid mGuid; }; -class DispatchWheelInputOnControllerThread : public Task +class DispatchWheelInputOnControllerThread : public Runnable { public: DispatchWheelInputOnControllerThread(const WidgetWheelEvent& aWheelEvent, APZCTreeManager* aAPZC, nsBaseWidget* aWidget) : mMainMessageLoop(MessageLoop::current()) , mWheelInput(aWheelEvent) , mAPZC(aAPZC) , mWidget(aWidget) , mInputBlockId(0) { } - void Run() + NS_IMETHOD Run() override { mAPZResult = mAPZC->ReceiveInputEvent(mWheelInput, &mGuid, &mInputBlockId); if (mAPZResult == nsEventStatus_eConsumeNoDefault) { - return; + return NS_OK; } - mMainMessageLoop->PostTask(FROM_HERE, - new DispatchWheelEventOnMainThread(mWheelInput, mWidget, mAPZResult, mInputBlockId, mGuid)); - return; + RefPtr<Runnable> r = new DispatchWheelEventOnMainThread(mWheelInput, mWidget, mAPZResult, mInputBlockId, mGuid); + mMainMessageLoop->PostTask(r.forget()); + return NS_OK; } private: MessageLoop* mMainMessageLoop; ScrollWheelInput mWheelInput; RefPtr<APZCTreeManager> mAPZC; nsBaseWidget* mWidget; nsEventStatus mAPZResult; @@ -1182,17 +1182,18 @@ nsBaseWidget::DispatchInputEvent(WidgetI nsEventStatus result = mAPZC->ReceiveInputEvent(*aEvent, &guid, &inputBlockId); if (result == nsEventStatus_eConsumeNoDefault) { return result; } return ProcessUntransformedAPZEvent(aEvent, guid, inputBlockId, result); } else { WidgetWheelEvent* wheelEvent = aEvent->AsWheelEvent(); if (wheelEvent) { - APZThreadUtils::RunOnControllerThread(new DispatchWheelInputOnControllerThread(*wheelEvent, mAPZC, this)); + RefPtr<Runnable> r = new DispatchWheelInputOnControllerThread(*wheelEvent, mAPZC, this); + APZThreadUtils::RunOnControllerThread(r.forget()); return nsEventStatus_eConsumeDoDefault; } MOZ_CRASH(); } } nsEventStatus status; DispatchEvent(aEvent, status);
--- a/xpcom/base/nsDumpUtils.cpp +++ b/xpcom/base/nsDumpUtils.cpp @@ -70,17 +70,16 @@ void FdWatcher::Init() { MOZ_ASSERT(NS_IsMainThread()); nsCOMPtr<nsIObserverService> os = services::GetObserverService(); os->AddObserver(this, "xpcom-shutdown", /* ownsWeak = */ false); XRE_GetIOMessageLoop()->PostTask( - FROM_HERE, NewRunnableMethod(this, &FdWatcher::StartWatching)); } // Implementations may call this function multiple times if they ensure that // it's safe to call OpenFd() multiple times and they call StopWatching() // first. void FdWatcher::StartWatching()
--- a/xpcom/base/nsDumpUtils.h +++ b/xpcom/base/nsDumpUtils.h @@ -85,17 +85,16 @@ public: NS_IMETHOD Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData) override { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(!strcmp(aTopic, "xpcom-shutdown")); XRE_GetIOMessageLoop()->PostTask( - FROM_HERE, NewRunnableMethod(this, &FdWatcher::StopWatching)); return NS_OK; } }; typedef void (*FifoCallback)(const nsCString& aInputStr); struct FifoInfo
--- a/xpcom/base/nsMessageLoop.cpp +++ b/xpcom/base/nsMessageLoop.cpp @@ -23,23 +23,23 @@ namespace { * This Task runs its nsIRunnable when Run() is called, or after * aEnsureRunsAfterMS milliseconds have elapsed since the object was * constructed. * * Note that the MessageLoop owns this object and will delete it after it calls * Run(). Tread lightly. */ class MessageLoopIdleTask - : public Task + : public Runnable , public SupportsWeakPtr<MessageLoopIdleTask> { public: MOZ_DECLARE_WEAKREFERENCE_TYPENAME(MessageLoopIdleTask) MessageLoopIdleTask(nsIRunnable* aTask, uint32_t aEnsureRunsAfterMS); - virtual void Run(); + NS_IMETHOD Run() override; private: nsresult Init(uint32_t aEnsureRunsAfterMS); nsCOMPtr<nsIRunnable> mTask; nsCOMPtr<nsITimer> mTimer; virtual ~MessageLoopIdleTask() {} @@ -97,32 +97,34 @@ MessageLoopIdleTask::Init(uint32_t aEnsu RefPtr<MessageLoopTimerCallback> callback = new MessageLoopTimerCallback(this); return mTimer->InitWithCallback(callback, aEnsureRunsAfterMS, nsITimer::TYPE_ONE_SHOT); } -/* virtual */ void +NS_IMETHODIMP MessageLoopIdleTask::Run() { // Null out our pointers because if Run() was called by the timer, this // object will be kept alive by the MessageLoop until the MessageLoop calls // Run(). if (mTimer) { mTimer->Cancel(); mTimer = nullptr; } if (mTask) { mTask->Run(); mTask = nullptr; } + + return NS_OK; } MessageLoopTimerCallback::MessageLoopTimerCallback(MessageLoopIdleTask* aTask) : mTask(aTask) { } NS_IMETHODIMP @@ -145,18 +147,20 @@ NS_IMPL_ISUPPORTS(MessageLoopTimerCallba NS_IMPL_ISUPPORTS(nsMessageLoop, nsIMessageLoop) NS_IMETHODIMP nsMessageLoop::PostIdleTask(nsIRunnable* aTask, uint32_t aEnsureRunsAfterMS) { // The message loop owns MessageLoopIdleTask and deletes it after calling // Run(). Be careful... - MessageLoop::current()->PostIdleTask(FROM_HERE, - new MessageLoopIdleTask(aTask, aEnsureRunsAfterMS)); + RefPtr<MessageLoopIdleTask> idle = + new MessageLoopIdleTask(aTask, aEnsureRunsAfterMS); + MessageLoop::current()->PostIdleTask(idle.forget()); + return NS_OK; } nsresult nsMessageLoopConstructor(nsISupports* aOuter, const nsIID& aIID, void** aInstancePtr) {