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 mozilla_dom_workers_WorkerThread_h__
8 #define mozilla_dom_workers_WorkerThread_h__
9 
10 #include "mozilla/AlreadyAddRefed.h"
11 #include "mozilla/CondVar.h"
12 #include "mozilla/Mutex.h"
13 #include "mozilla/PerformanceCounter.h"
14 #include "mozilla/RefPtr.h"
15 #include "mozilla/dom/SafeRefPtr.h"
16 #include "nsISupports.h"
17 #include "nsThread.h"
18 #include "nscore.h"
19 
20 class nsIRunnable;
21 
22 namespace mozilla {
23 class Runnable;
24 
25 namespace dom {
26 
27 class WorkerRunnable;
28 class WorkerPrivate;
29 template <class>
30 class WorkerPrivateParent;
31 
32 namespace workerinternals {
33 class RuntimeService;
34 }
35 
36 // This class lets us restrict the public methods that can be called on
37 // WorkerThread to RuntimeService and WorkerPrivate without letting them gain
38 // full access to private methods (as would happen if they were simply friends).
39 class WorkerThreadFriendKey {
40   friend class workerinternals::RuntimeService;
41   friend class WorkerPrivate;
42   friend class WorkerPrivateParent<WorkerPrivate>;
43 
44   WorkerThreadFriendKey();
45   ~WorkerThreadFriendKey();
46 };
47 
48 class WorkerThread final : public nsThread {
49   class Observer;
50 
51   Mutex mLock;
52   CondVar mWorkerPrivateCondVar;
53 
54   // Protected by nsThread::mLock.
55   WorkerPrivate* mWorkerPrivate;
56 
57   // Only touched on the target thread.
58   RefPtr<Observer> mObserver;
59 
60   // Protected by nsThread::mLock and waited on with mWorkerPrivateCondVar.
61   uint32_t mOtherThreadsDispatchingViaEventTarget;
62 
63 #ifdef DEBUG
64   // Protected by nsThread::mLock.
65   bool mAcceptingNonWorkerRunnables;
66 #endif
67 
68   // Using this struct we restrict access to the constructor while still being
69   // able to use MakeSafeRefPtr.
70   struct ConstructorKey {};
71 
72  public:
73   explicit WorkerThread(ConstructorKey);
74 
75   static SafeRefPtr<WorkerThread> Create(const WorkerThreadFriendKey& aKey);
76 
77   void SetWorker(const WorkerThreadFriendKey& aKey,
78                  WorkerPrivate* aWorkerPrivate);
79 
80   nsresult DispatchPrimaryRunnable(const WorkerThreadFriendKey& aKey,
81                                    already_AddRefed<nsIRunnable> aRunnable);
82 
83   nsresult DispatchAnyThread(const WorkerThreadFriendKey& aKey,
84                              already_AddRefed<WorkerRunnable> aWorkerRunnable);
85 
86   uint32_t RecursionDepth(const WorkerThreadFriendKey& aKey) const;
87 
88   PerformanceCounter* GetPerformanceCounter(nsIRunnable* aEvent) const override;
89 
90   NS_INLINE_DECL_REFCOUNTING_INHERITED(WorkerThread, nsThread)
91 
92  private:
93   ~WorkerThread();
94 
95   // This should only be called by consumers that have an
96   // nsIEventTarget/nsIThread pointer.
97   NS_IMETHOD
98   Dispatch(already_AddRefed<nsIRunnable> aRunnable, uint32_t aFlags) override;
99 
100   NS_IMETHOD
101   DispatchFromScript(nsIRunnable* aRunnable, uint32_t aFlags) override;
102 
103   NS_IMETHOD
104   DelayedDispatch(already_AddRefed<nsIRunnable>, uint32_t) override;
105 
106   void IncrementDispatchCounter();
107 };
108 
109 }  // namespace dom
110 }  // namespace mozilla
111 
112 #endif  // mozilla_dom_workers_WorkerThread_h__
113