1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "mozilla/mscom/EnsureMTA.h" 8 9 #include "mozilla/ClearOnShutdown.h" 10 #include "mozilla/StaticPtr.h" 11 #include "nsThreadUtils.h" 12 13 #include "private/pprthred.h" 14 15 namespace { 16 17 class EnterMTARunnable : public mozilla::Runnable { 18 public: EnterMTARunnable()19 EnterMTARunnable() : mozilla::Runnable("EnterMTARunnable") {} Run()20 NS_IMETHOD Run() override { 21 mozilla::DebugOnly<HRESULT> hr = 22 ::CoInitializeEx(nullptr, COINIT_MULTITHREADED); 23 MOZ_ASSERT(SUCCEEDED(hr)); 24 return NS_OK; 25 } 26 }; 27 28 class BackgroundMTAData { 29 public: BackgroundMTAData()30 BackgroundMTAData() { 31 nsCOMPtr<nsIRunnable> runnable = new EnterMTARunnable(); 32 mozilla::DebugOnly<nsresult> rv = 33 NS_NewNamedThread("COM MTA", getter_AddRefs(mThread), runnable); 34 NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "NS_NewNamedThread failed"); 35 MOZ_ASSERT(NS_SUCCEEDED(rv)); 36 } 37 ~BackgroundMTAData()38 ~BackgroundMTAData() { 39 if (mThread) { 40 mThread->Dispatch( 41 NS_NewRunnableFunction("BackgroundMTAData::~BackgroundMTAData", 42 &::CoUninitialize), 43 NS_DISPATCH_NORMAL); 44 mThread->Shutdown(); 45 } 46 } 47 GetThread() const48 nsCOMPtr<nsIThread> GetThread() const { return mThread; } 49 50 private: 51 nsCOMPtr<nsIThread> mThread; 52 }; 53 54 } // anonymous namespace 55 56 static mozilla::StaticAutoPtr<BackgroundMTAData> sMTAData; 57 58 namespace mozilla { 59 namespace mscom { 60 GetMTAThread()61/* static */ nsCOMPtr<nsIThread> EnsureMTA::GetMTAThread() { 62 if (!sMTAData) { 63 sMTAData = new BackgroundMTAData(); 64 ClearOnShutdown(&sMTAData, ShutdownPhase::ShutdownThreads); 65 } 66 return sMTAData->GetThread(); 67 } 68 69 } // namespace mscom 70 } // namespace mozilla 71