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