Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/mozilla/SharedThreadPool.h
Line
Count
Source (jump to first uncovered line)
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
#ifndef SharedThreadPool_h_
8
#define SharedThreadPool_h_
9
10
#include <queue>
11
#include "mozilla/RefPtr.h"
12
#include "nsThreadUtils.h"
13
#include "nsIThreadManager.h"
14
#include "nsIThreadPool.h"
15
#include "nsISupports.h"
16
#include "nsISupportsImpl.h"
17
#include "nsCOMPtr.h"
18
19
namespace mozilla {
20
21
// Wrapper that makes an nsIThreadPool a singleton, and provides a
22
// consistent threadsafe interface to get instances. Callers simply get a
23
// SharedThreadPool by the name of its nsIThreadPool. All get requests of
24
// the same name get the same SharedThreadPool. Users must store a reference
25
// to the pool, and when the last reference to a SharedThreadPool is dropped
26
// the pool is shutdown and deleted. Users aren't required to manually
27
// shutdown the pool, and can release references on any thread. This can make
28
// it significantly easier to use thread pools, because the caller doesn't need
29
// to worry about joining and tearing it down.
30
//
31
// On Windows all threads in the pool have MSCOM initialized with
32
// COINIT_MULTITHREADED. Note that not all users of MSCOM use this mode see [1],
33
// and mixing MSCOM objects between the two is terrible for performance, and can
34
// cause some functions to fail. So be careful when using Win32 APIs on a
35
// SharedThreadPool, and avoid sharing objects if at all possible.
36
//
37
// [1] https://dxr.mozilla.org/mozilla-central/search?q=coinitialize&redirect=false
38
class SharedThreadPool : public nsIThreadPool
39
{
40
public:
41
42
  // Gets (possibly creating) the shared thread pool singleton instance with
43
  // thread pool named aName.
44
  static already_AddRefed<SharedThreadPool> Get(const nsCString& aName,
45
                                            uint32_t aThreadLimit = 4);
46
47
  // We implement custom threadsafe AddRef/Release pair, that destroys the
48
  // the shared pool singleton when the refcount drops to 0. The addref/release
49
  // are implemented using locking, so it's not recommended that you use them
50
  // in a tight loop.
51
  NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
52
  NS_IMETHOD_(MozExternalRefCountType) AddRef(void) override;
53
  NS_IMETHOD_(MozExternalRefCountType) Release(void) override;
54
55
  // Forward behaviour to wrapped thread pool implementation.
56
  NS_FORWARD_SAFE_NSITHREADPOOL(mPool);
57
58
  // Call this when dispatching from an event on the same
59
  // threadpool that is about to complete. We should not create a new thread
60
  // in that case since a thread is about to become idle.
61
  nsresult DispatchFromEndOfTaskInThisPool(nsIRunnable *event)
62
0
  {
63
0
    return Dispatch(event, NS_DISPATCH_AT_END);
64
0
  }
65
66
0
  NS_IMETHOD DispatchFromScript(nsIRunnable *event, uint32_t flags) override {
67
0
      return Dispatch(event, flags);
68
0
  }
69
70
  NS_IMETHOD Dispatch(already_AddRefed<nsIRunnable> event, uint32_t flags = NS_DISPATCH_NORMAL) override
71
0
    { return !mEventTarget ? NS_ERROR_NULL_POINTER : mEventTarget->Dispatch(std::move(event), flags); }
72
73
  NS_IMETHOD DelayedDispatch(already_AddRefed<nsIRunnable>, uint32_t) override
74
0
    { return NS_ERROR_NOT_IMPLEMENTED; }
75
76
  using nsIEventTarget::Dispatch;
77
78
0
  NS_IMETHOD IsOnCurrentThread(bool *_retval) override { return !mEventTarget ? NS_ERROR_NULL_POINTER : mEventTarget->IsOnCurrentThread(_retval); }
79
80
0
  NS_IMETHOD_(bool) IsOnCurrentThreadInfallible() override { return mEventTarget && mEventTarget->IsOnCurrentThread(); }
81
82
  // Creates necessary statics. Called once at startup.
83
  static void InitStatics();
84
85
  // Spins the event loop until all thread pools are shutdown.
86
  // *Must* be called on the main thread.
87
  static void SpinUntilEmpty();
88
89
private:
90
91
  // Returns whether there are no pools in existence at the moment.
92
  static bool IsEmpty();
93
94
  // Creates a singleton SharedThreadPool wrapper around aPool.
95
  // aName is the name of the aPool, and is used to lookup the
96
  // SharedThreadPool in the hash table of all created pools.
97
  SharedThreadPool(const nsCString& aName,
98
                   nsIThreadPool* aPool);
99
  virtual ~SharedThreadPool();
100
101
  nsresult EnsureThreadLimitIsAtLeast(uint32_t aThreadLimit);
102
103
  // Name of mPool.
104
  const nsCString mName;
105
106
  // Thread pool being wrapped.
107
  nsCOMPtr<nsIThreadPool> mPool;
108
109
  // Refcount. We implement custom ref counting so that the thread pool is
110
  // shutdown in a threadsafe manner and singletonness is preserved.
111
  nsrefcnt mRefCnt;
112
113
  // mPool QI'd to nsIEventTarget. We cache this, so that we can use
114
  // NS_FORWARD_SAFE_NSIEVENTTARGET above.
115
  nsCOMPtr<nsIEventTarget> mEventTarget;
116
};
117
118
} // namespace mozilla
119
120
#endif // SharedThreadPool_h_