michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim:set ts=2 sw=2 sts=2 et cindent: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef SharedThreadPool_h_ michael@0: #define SharedThreadPool_h_ michael@0: michael@0: #include michael@0: #include "mozilla/RefPtr.h" michael@0: #include "nsThreadUtils.h" michael@0: #include "nsIThreadPool.h" michael@0: #include "nsISupports.h" michael@0: #include "nsISupportsImpl.h" michael@0: #include "nsCOMPtr.h" michael@0: michael@0: namespace mozilla { michael@0: michael@0: // Wrapper that makes an nsIThreadPool a singleton, and provides a michael@0: // consistent threadsafe interface to get instances. Callers simply get a michael@0: // SharedThreadPool by the name of its nsIThreadPool. All get requests of michael@0: // the same name get the same SharedThreadPool. Users must store a reference michael@0: // to the pool, and when the last reference to a SharedThreadPool is dropped michael@0: // the pool is shutdown and deleted. Users aren't required to manually michael@0: // shutdown the pool, and can release references on any thread. On Windows michael@0: // all threads in the pool have MSCOM initialized with COINIT_MULTITHREADED. michael@0: class SharedThreadPool : public nsIThreadPool michael@0: { michael@0: public: michael@0: michael@0: // Gets (possibly creating) the shared thread pool singleton instance with michael@0: // thread pool named aName. michael@0: // *Must* be called on the main thread. michael@0: static TemporaryRef Get(const nsCString& aName, michael@0: uint32_t aThreadLimit = 4); michael@0: michael@0: // Spins the event loop until all thread pools are shutdown. michael@0: // *Must* be called on the main thread. michael@0: static void SpinUntilShutdown(); michael@0: michael@0: // We implement custom threadsafe AddRef/Release pair, that destroys the michael@0: // the shared pool singleton when the refcount drops to 0. The addref/release michael@0: // are implemented using locking, so it's not recommended that you use them michael@0: // in a tight loop. michael@0: NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr); michael@0: NS_IMETHOD_(MozExternalRefCountType) AddRef(void); michael@0: NS_IMETHOD_(MozExternalRefCountType) Release(void); michael@0: michael@0: // Forward behaviour to wrapped thread pool implementation. michael@0: NS_FORWARD_SAFE_NSITHREADPOOL(mPool); michael@0: NS_FORWARD_SAFE_NSIEVENTTARGET(GetEventTarget()); michael@0: michael@0: nsIEventTarget* GetEventTarget() { michael@0: return mEventTarget; michael@0: } michael@0: michael@0: private: michael@0: michael@0: // Creates necessary statics. michael@0: // Main thread only. michael@0: static void EnsureInitialized(); michael@0: michael@0: // Creates a singleton SharedThreadPool wrapper around aPool. michael@0: // aName is the name of the aPool, and is used to lookup the michael@0: // SharedThreadPool in the hash table of all created pools. michael@0: SharedThreadPool(const nsCString& aName, michael@0: nsIThreadPool* aPool); michael@0: virtual ~SharedThreadPool(); michael@0: michael@0: nsresult EnsureThreadLimitIsAtLeast(uint32_t aThreadLimit); michael@0: michael@0: // Name of mPool. michael@0: const nsCString mName; michael@0: michael@0: // Thread pool being wrapped. michael@0: nsCOMPtr mPool; michael@0: michael@0: // Refcount. We implement custom ref counting so that the thread pool is michael@0: // shutdown in a threadsafe manner and singletonness is preserved. michael@0: nsrefcnt mRefCnt; michael@0: michael@0: // mPool QI'd to nsIEventTarget. We cache this, so that we can use michael@0: // NS_FORWARD_SAFE_NSIEVENTTARGET above. michael@0: nsCOMPtr mEventTarget; michael@0: }; michael@0: michael@0: } // namespace mozilla michael@0: michael@0: #endif // SharedThreadPool_h_