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 https://mozilla.org/MPL/2.0/. */
6 
7 #ifndef mozilla_GraphRunner_h
8 #define mozilla_GraphRunner_h
9 
10 #include "GraphDriver.h"
11 #include "MediaSegment.h"
12 #include "mozilla/Monitor.h"
13 
14 #include <thread>
15 
16 struct PRThread;
17 
18 namespace mozilla {
19 
20 class AudioMixer;
21 class MediaTrackGraphImpl;
22 
23 class GraphRunner final : public Runnable {
24   using IterationResult = GraphInterface::IterationResult;
25 
26  public:
27   static already_AddRefed<GraphRunner> Create(MediaTrackGraphImpl* aGraph);
28 
29   /**
30    * Marks us as shut down and signals mThread, so that it runs until the end.
31    */
32   MOZ_CAN_RUN_SCRIPT void Shutdown();
33 
34   /**
35    * Signals one iteration of mGraph. Hands state over to mThread and runs
36    * the iteration there.
37    */
38   IterationResult OneIteration(GraphTime aStateEnd, GraphTime aIterationEnd,
39                                AudioMixer* aMixer);
40 
41   /**
42    * Runs mGraph until it shuts down.
43    */
44   NS_IMETHOD Run();
45 
46   /**
47    * Returns true if called on mThread.
48    */
49   bool OnThread();
50 
51 #ifdef DEBUG
52   /**
53    * Returns true if called on mThread, and aDriver was the driver that called
54    * OneIteration() last.
55    */
56   bool InDriverIteration(GraphDriver* aDriver);
57 #endif
58 
59  private:
60   explicit GraphRunner(MediaTrackGraphImpl* aGraph,
61                        already_AddRefed<nsIThread> aThread);
62   ~GraphRunner();
63 
64   class IterationState {
65     GraphTime mStateEnd;
66     GraphTime mIterationEnd;
67     AudioMixer* MOZ_NON_OWNING_REF mMixer;
68 
69    public:
IterationState(GraphTime aStateEnd,GraphTime aIterationEnd,AudioMixer * aMixer)70     IterationState(GraphTime aStateEnd, GraphTime aIterationEnd,
71                    AudioMixer* aMixer)
72         : mStateEnd(aStateEnd), mIterationEnd(aIterationEnd), mMixer(aMixer) {}
73     IterationState& operator=(const IterationState& aOther) = default;
StateEnd()74     GraphTime StateEnd() const { return mStateEnd; }
IterationEnd()75     GraphTime IterationEnd() const { return mIterationEnd; }
Mixer()76     AudioMixer* Mixer() const { return mMixer; }
77   };
78 
79   // Monitor used for yielding mThread through Wait(), and scheduling mThread
80   // through Signal() from a GraphDriver.
81   Monitor mMonitor;
82   // The MediaTrackGraph we're running. Weakptr beecause this graph owns us and
83   // guarantees that our lifetime will not go beyond that of itself.
84   MediaTrackGraphImpl* const mGraph;
85   // State being handed over to the graph through OneIteration. Protected by
86   // mMonitor.
87   Maybe<IterationState> mIterationState;
88   // Result from mGraph's OneIteration. Protected by mMonitor.
89   IterationResult mIterationResult;
90 
91   enum class ThreadState {
92     Wait,      // Waiting for a message.  This is the initial state.
93                // A transition from Run back to Wait occurs on the runner
94                // thread after it processes as far as mIterationState->mStateEnd
95                // and sets mIterationResult.
96     Run,       // Set on driver thread after each mIterationState update.
97     Shutdown,  // Set when Shutdown() is called on main thread.
98   };
99   // Protected by mMonitor until set to Shutdown, after which this is not
100   // modified.
101   ThreadState mThreadState;
102 
103   // The thread running mGraph.  Set on construction, after other members are
104   // initialized.  Cleared at the end of Shutdown().
105   const nsCOMPtr<nsIThread> mThread;
106 
107 #ifdef DEBUG
108   // Set to mGraph's audio callback driver's thread id, if run by an
109   // AudioCallbackDriver, while OneIteration() is running.
110   std::thread::id mAudioDriverThreadId = std::thread::id();
111   // Set to mGraph's system clock driver's thread, if run by a
112   // SystemClockDriver, while OneIteration() is running.
113   nsIThread* mClockDriverThread = nullptr;
114 #endif
115 };
116 
117 }  // namespace mozilla
118 
119 #endif
120