|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */ |
|
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 #ifndef SharedThreadPool_h_ |
|
8 #define SharedThreadPool_h_ |
|
9 |
|
10 #include <queue> |
|
11 #include "mozilla/RefPtr.h" |
|
12 #include "nsThreadUtils.h" |
|
13 #include "nsIThreadPool.h" |
|
14 #include "nsISupports.h" |
|
15 #include "nsISupportsImpl.h" |
|
16 #include "nsCOMPtr.h" |
|
17 |
|
18 namespace mozilla { |
|
19 |
|
20 // Wrapper that makes an nsIThreadPool a singleton, and provides a |
|
21 // consistent threadsafe interface to get instances. Callers simply get a |
|
22 // SharedThreadPool by the name of its nsIThreadPool. All get requests of |
|
23 // the same name get the same SharedThreadPool. Users must store a reference |
|
24 // to the pool, and when the last reference to a SharedThreadPool is dropped |
|
25 // the pool is shutdown and deleted. Users aren't required to manually |
|
26 // shutdown the pool, and can release references on any thread. On Windows |
|
27 // all threads in the pool have MSCOM initialized with COINIT_MULTITHREADED. |
|
28 class SharedThreadPool : public nsIThreadPool |
|
29 { |
|
30 public: |
|
31 |
|
32 // Gets (possibly creating) the shared thread pool singleton instance with |
|
33 // thread pool named aName. |
|
34 // *Must* be called on the main thread. |
|
35 static TemporaryRef<SharedThreadPool> Get(const nsCString& aName, |
|
36 uint32_t aThreadLimit = 4); |
|
37 |
|
38 // Spins the event loop until all thread pools are shutdown. |
|
39 // *Must* be called on the main thread. |
|
40 static void SpinUntilShutdown(); |
|
41 |
|
42 // We implement custom threadsafe AddRef/Release pair, that destroys the |
|
43 // the shared pool singleton when the refcount drops to 0. The addref/release |
|
44 // are implemented using locking, so it's not recommended that you use them |
|
45 // in a tight loop. |
|
46 NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr); |
|
47 NS_IMETHOD_(MozExternalRefCountType) AddRef(void); |
|
48 NS_IMETHOD_(MozExternalRefCountType) Release(void); |
|
49 |
|
50 // Forward behaviour to wrapped thread pool implementation. |
|
51 NS_FORWARD_SAFE_NSITHREADPOOL(mPool); |
|
52 NS_FORWARD_SAFE_NSIEVENTTARGET(GetEventTarget()); |
|
53 |
|
54 nsIEventTarget* GetEventTarget() { |
|
55 return mEventTarget; |
|
56 } |
|
57 |
|
58 private: |
|
59 |
|
60 // Creates necessary statics. |
|
61 // Main thread only. |
|
62 static void EnsureInitialized(); |
|
63 |
|
64 // Creates a singleton SharedThreadPool wrapper around aPool. |
|
65 // aName is the name of the aPool, and is used to lookup the |
|
66 // SharedThreadPool in the hash table of all created pools. |
|
67 SharedThreadPool(const nsCString& aName, |
|
68 nsIThreadPool* aPool); |
|
69 virtual ~SharedThreadPool(); |
|
70 |
|
71 nsresult EnsureThreadLimitIsAtLeast(uint32_t aThreadLimit); |
|
72 |
|
73 // Name of mPool. |
|
74 const nsCString mName; |
|
75 |
|
76 // Thread pool being wrapped. |
|
77 nsCOMPtr<nsIThreadPool> mPool; |
|
78 |
|
79 // Refcount. We implement custom ref counting so that the thread pool is |
|
80 // shutdown in a threadsafe manner and singletonness is preserved. |
|
81 nsrefcnt mRefCnt; |
|
82 |
|
83 // mPool QI'd to nsIEventTarget. We cache this, so that we can use |
|
84 // NS_FORWARD_SAFE_NSIEVENTTARGET above. |
|
85 nsCOMPtr<nsIEventTarget> mEventTarget; |
|
86 }; |
|
87 |
|
88 } // namespace mozilla |
|
89 |
|
90 #endif // SharedThreadPool_h_ |