IVGCVSW-5675 Implement Pimpl Idiom for IProfiler (lower priority)

Signed-off-by: Francis Murtagh <francis.murtagh@arm.com>
Change-Id: If716f5f4e9b5433586b8a939d326830482da2f74
diff --git a/include/armnn/IProfiler.hpp b/include/armnn/IProfiler.hpp
index 5e6f508..ac422b7 100644
--- a/include/armnn/IProfiler.hpp
+++ b/include/armnn/IProfiler.hpp
@@ -6,33 +6,50 @@
 #pragma once
 
 #include <iostream>
+#include <memory>
+#include <vector>
 
 namespace armnn
 {
 
+class ProfilerImpl;
+class BackendId;
+class Instrument;
+class Event;
 class IProfiler
 {
 public:
     /// Enables/disables profiling for this profiler.
     /// @param [in] enableProfiling A flag that indicates whether profiling should be enabled or not.
-    virtual void EnableProfiling(bool enableProfiling) = 0;
+    void EnableProfiling(bool enableProfiling);
 
     /// Checks whether profiling is enabled.
     /// Profiling is disabled by default.
     /// @return true if profiling is enabled, false otherwise.
-    virtual bool IsProfilingEnabled() = 0;
+    bool IsProfilingEnabled();
 
     /// Analyzes the tracked events and writes the results to the given output stream.
     /// Please refer to the configuration variables in Profiling.cpp to customize the information written.
     /// @param [out] outStream The stream where to write the profiling results to.
-    virtual void AnalyzeEventsAndWriteResults(std::ostream& outStream) const = 0;
+    void AnalyzeEventsAndWriteResults(std::ostream& outStream) const;
 
     /// Print stats for events in JSON Format to the given output stream.
     /// @param [out] outStream The stream where to write the profiling results to.
-    virtual void Print(std::ostream& outStream) const = 0;
+    void Print(std::ostream& outStream) const;
 
-protected:
-    ~IProfiler() {}
+    ~IProfiler();
+    IProfiler();
+
+private:
+    using InstrumentPtr = std::unique_ptr<Instrument>;
+    Event* BeginEvent(const BackendId& backendId,
+                      const std::string& label,
+                      std::vector<InstrumentPtr>&& instruments);
+    std::unique_ptr<ProfilerImpl> pProfilerImpl;
+    friend class ScopedProfilingEvent;
+
+    // Friend functions for unit testing, see ProfilerTests.cpp.
+    friend size_t GetProfilerEventSequenceSize(armnn::IProfiler* profiler);
 };
 
 } // namespace armnn
diff --git a/src/armnn/LoadedNetwork.cpp b/src/armnn/LoadedNetwork.cpp
index f851910..4a307e2 100644
--- a/src/armnn/LoadedNetwork.cpp
+++ b/src/armnn/LoadedNetwork.cpp
@@ -125,7 +125,7 @@
                              m_ProfilingService(profilingService)
 {
     // Create a profiler and register it for the current thread.
-    m_Profiler = std::make_shared<Profiler>();
+    m_Profiler = std::make_shared<IProfiler>();
     ProfilerManager::GetInstance().RegisterProfiler(m_Profiler.get());
 
     Graph& order = m_OptimizedNetwork->GetGraph().TopologicalSort();
diff --git a/src/armnn/LoadedNetwork.hpp b/src/armnn/LoadedNetwork.hpp
index 39b6089..3a44206 100644
--- a/src/armnn/LoadedNetwork.hpp
+++ b/src/armnn/LoadedNetwork.hpp
@@ -50,7 +50,7 @@
     // NOTE we return by reference as the purpose of this method is only to provide
     // access to the private m_Profiler and in theory we should not need to increment
     // the shared_ptr's reference counter
-    const std::shared_ptr<Profiler>& GetProfiler() const { return m_Profiler; }
+    const std::shared_ptr<IProfiler>& GetProfiler() const { return m_Profiler; }
 
     void FreeWorkingMemory();
 
@@ -91,7 +91,7 @@
     WorkloadQueue m_InputQueue;
     WorkloadQueue m_WorkloadQueue;
     WorkloadQueue m_OutputQueue;
-    std::shared_ptr<Profiler> m_Profiler;
+    std::shared_ptr<IProfiler> m_Profiler;
 
     mutable std::mutex m_WorkingMemMutex;
 
diff --git a/src/armnn/Profiling.cpp b/src/armnn/Profiling.cpp
index 1cdf30c..c30b482 100644
--- a/src/armnn/Profiling.cpp
+++ b/src/armnn/Profiling.cpp
@@ -80,7 +80,7 @@
     return measurements;
 }
 
-std::map<std::string, Profiler::ProfilingEventStats> Profiler::CalculateProfilingEventStats() const
+std::map<std::string, ProfilerImpl::ProfilingEventStats> ProfilerImpl::CalculateProfilingEventStats() const
 {
     std::map<std::string, ProfilingEventStats> nameToStatsMap;
 
@@ -111,7 +111,7 @@
 const Event* GetEventPtr(const std::unique_ptr<Event>& ptr) {return ptr.get(); }
 
 template<typename ItertType>
-void Profiler::AnalyzeEventSequenceAndWriteResults(ItertType first, ItertType last, std::ostream& outStream) const
+void ProfilerImpl::AnalyzeEventSequenceAndWriteResults(ItertType first, ItertType last, std::ostream& outStream) const
 {
     // Outputs event sequence, if needed.
     if (g_WriteProfilingEventSequence)
@@ -162,7 +162,7 @@
     outStream << std::endl;
 }
 
-Profiler::Profiler()
+ProfilerImpl::ProfilerImpl()
     : m_ProfilingEnabled(false)
 {
     m_EventSequence.reserve(g_ProfilingEventCountHint);
@@ -173,7 +173,7 @@
 #endif
 }
 
-Profiler::~Profiler()
+ProfilerImpl::~ProfilerImpl()
 {
     if (m_ProfilingEnabled)
     {
@@ -187,22 +187,23 @@
     ProfilerManager::GetInstance().RegisterProfiler(nullptr);
 }
 
-bool Profiler::IsProfilingEnabled()
+bool ProfilerImpl::IsProfilingEnabled()
 {
     return m_ProfilingEnabled;
 }
 
-void Profiler::EnableProfiling(bool enableProfiling)
+void ProfilerImpl::EnableProfiling(bool enableProfiling)
 {
     m_ProfilingEnabled = enableProfiling;
 }
 
-Event* Profiler::BeginEvent(const BackendId& backendId,
+Event* ProfilerImpl::BeginEvent(armnn::IProfiler* profiler,
+                            const BackendId& backendId,
                             const std::string& label,
                             std::vector<InstrumentPtr>&& instruments)
 {
     Event* parent = m_Parents.empty() ? nullptr : m_Parents.top();
-    m_EventSequence.push_back(std::make_unique<Event>(label, this, parent, backendId, std::move(instruments)));
+    m_EventSequence.push_back(std::make_unique<Event>(label, profiler, parent, backendId, std::move(instruments)));
     Event* event = m_EventSequence.back().get();
     event->Start();
 
@@ -214,7 +215,7 @@
     return event;
 }
 
-void Profiler::EndEvent(Event* event)
+void ProfilerImpl::EndEvent(Event* event)
 {
     event->Stop();
 
@@ -242,7 +243,7 @@
     return level;
 }
 
-void Profiler::PopulateInferences(std::vector<const Event*>& outInferences, int& outBaseLevel) const
+void ProfilerImpl::PopulateInferences(std::vector<const Event*>& outInferences, int& outBaseLevel) const
 {
     outInferences.reserve(m_EventSequence.size());
     for (const auto& event : m_EventSequence)
@@ -256,7 +257,7 @@
     }
 }
 
-void Profiler::PopulateDescendants(std::map<const Event*, std::vector<const Event*>>& outDescendantsMap) const
+void ProfilerImpl::PopulateDescendants(std::map<const Event*, std::vector<const Event*>>& outDescendantsMap) const
 {
     for (const auto& event : m_EventSequence)
     {
@@ -327,7 +328,7 @@
     }
 }
 
-void Profiler::Print(std::ostream& outStream) const
+void ProfilerImpl::Print(std::ostream& outStream) const
 {
     // Makes sure timestamps are output with 6 decimals, and save old settings.
     std::streamsize oldPrecision = outStream.precision();
@@ -377,7 +378,7 @@
     outStream.precision(oldPrecision);
 }
 
-void Profiler::AnalyzeEventsAndWriteResults(std::ostream& outStream) const
+void ProfilerImpl::AnalyzeEventsAndWriteResults(std::ostream& outStream) const
 {
     // Stack should be empty now.
     const bool saneMarkerSequence = m_Parents.empty();
@@ -460,7 +461,7 @@
     }
 }
 
-std::uint32_t Profiler::GetEventColor(const BackendId& backendId) const
+std::uint32_t ProfilerImpl::GetEventColor(const BackendId& backendId) const
 {
     static BackendId cpuRef("CpuRef");
     static BackendId cpuAcc("CpuAcc");
@@ -481,7 +482,9 @@
 }
 
 // The thread_local pointer to the profiler instance.
-thread_local Profiler* tl_Profiler = nullptr;
+thread_local IProfiler* tl_Profiler = nullptr;
+
+
 
 ProfilerManager& ProfilerManager::GetInstance()
 {
@@ -490,14 +493,45 @@
     return s_ProfilerManager;
 }
 
-void ProfilerManager::RegisterProfiler(Profiler* profiler)
+void ProfilerManager::RegisterProfiler(IProfiler* profiler)
 {
     tl_Profiler = profiler;
 }
 
-Profiler* ProfilerManager::GetProfiler()
+IProfiler* ProfilerManager::GetProfiler()
 {
     return tl_Profiler;
 }
 
+
+void IProfiler::EnableProfiling(bool enableProfiling)
+{
+    pProfilerImpl->EnableProfiling(enableProfiling);
+}
+
+bool IProfiler::IsProfilingEnabled()
+{
+    return pProfilerImpl->IsProfilingEnabled();
+}
+
+void IProfiler::AnalyzeEventsAndWriteResults(std::ostream& outStream) const
+{
+    pProfilerImpl->AnalyzeEventsAndWriteResults(outStream);
+}
+
+void IProfiler::Print(std::ostream& outStream) const
+{
+    pProfilerImpl->Print(outStream);
+}
+
+Event* IProfiler::BeginEvent(const BackendId& backendId,
+                  const std::string& label,
+                  std::vector<InstrumentPtr>&& instruments)
+{
+    return pProfilerImpl->BeginEvent(this, backendId, label,  std::move(instruments));
+}
+
+IProfiler::~IProfiler() = default;
+IProfiler::IProfiler() : pProfilerImpl(new ProfilerImpl()) {};
+
 } // namespace armnn
diff --git a/src/armnn/Profiling.hpp b/src/armnn/Profiling.hpp
index c0d37dc..d134425 100644
--- a/src/armnn/Profiling.hpp
+++ b/src/armnn/Profiling.hpp
@@ -24,40 +24,42 @@
 // Simple single-threaded profiler.
 // Tracks events reported by BeginEvent()/EndEvent() and outputs detailed information and stats when
 // Profiler::AnalyzeEventsAndWriteResults() is called.
-class Profiler final : public IProfiler
+class ProfilerImpl
 {
 public:
-    Profiler();
-    ~Profiler();
+    ProfilerImpl();
+    ~ProfilerImpl();
     using InstrumentPtr = std::unique_ptr<Instrument>;
 
     // Marks the beginning of a user-defined event.
     // No attempt will be made to copy the name string: it must be known at compile time.
-    Event* BeginEvent(const BackendId& backendId, const std::string& name, std::vector<InstrumentPtr>&& instruments);
+    Event* BeginEvent(armnn::IProfiler* profiler,
+                      const BackendId& backendId,
+                      const std::string& name,
+                      std::vector<InstrumentPtr>&& instruments);
 
     // Marks the end of a user-defined event.
     void EndEvent(Event* event);
 
     // Enables/disables profiling.
-    void EnableProfiling(bool enableProfiling) override;
+    void EnableProfiling(bool enableProfiling);
 
     // Checks if profiling is enabled.
-    bool IsProfilingEnabled() override;
+    bool IsProfilingEnabled();
 
     // Increments the event tag, allowing grouping of events in a user-defined manner (e.g. per inference).
     void UpdateEventTag();
 
     // Analyzes the tracked events and writes the results to the given output stream.
     // Please refer to the configuration variables in Profiling.cpp to customize the information written.
-    void AnalyzeEventsAndWriteResults(std::ostream& outStream) const override;
+    void AnalyzeEventsAndWriteResults(std::ostream& outStream) const;
 
     // Print stats for events in JSON Format to the given output stream.
-    void Print(std::ostream& outStream) const override;
+    void Print(std::ostream& outStream) const;
 
     // Gets the color to render an event with, based on which device it denotes.
     uint32_t GetEventColor(const BackendId& backendId) const;
 
-private:
     using EventPtr = std::unique_ptr<Event>;
     struct Marker
     {
@@ -82,10 +84,6 @@
     std::stack<Event*> m_Parents;
     std::vector<EventPtr> m_EventSequence;
     bool m_ProfilingEnabled;
-
-private:
-    // Friend functions for unit testing, see ProfilerTests.cpp.
-    friend size_t GetProfilerEventSequenceSize(armnn::Profiler* profiler);
 };
 
 // Singleton profiler manager.
@@ -94,10 +92,10 @@
 {
 public:
     // Register the given profiler as a thread local pointer.
-    void RegisterProfiler(Profiler* profiler);
+    void RegisterProfiler(IProfiler* profiler);
 
     // Gets the thread local pointer to the profiler.
-    Profiler* GetProfiler();
+    IProfiler* GetProfiler();
 
     // Accesses the singleton.
     static ProfilerManager& GetInstance();
@@ -132,7 +130,7 @@
     {
         if (m_Profiler && m_Event)
         {
-            m_Profiler->EndEvent(m_Event);
+            m_Profiler->pProfilerImpl->EndEvent(m_Event);
         }
     }
 
@@ -151,7 +149,7 @@
     }
 
     Event* m_Event;       ///< Event to track
-    Profiler* m_Profiler; ///< Profiler used
+    IProfiler* m_Profiler; ///< Profiler used
 };
 
 } // namespace armnn
diff --git a/src/armnn/ProfilingEvent.cpp b/src/armnn/ProfilingEvent.cpp
index 60fb2f7..1ba9789 100644
--- a/src/armnn/ProfilingEvent.cpp
+++ b/src/armnn/ProfilingEvent.cpp
@@ -9,7 +9,7 @@
 namespace armnn
 {
 Event::Event(const std::string& eventName,
-             Profiler* profiler,
+             IProfiler* profiler,
              Event* parent,
              const BackendId backendId,
              std::vector<InstrumentPtr>&& instruments)
@@ -69,7 +69,7 @@
     return m_EventName;
 }
 
-const Profiler* Event::GetProfiler() const
+const IProfiler* Event::GetProfiler() const
 {
     return m_Profiler;
 }
diff --git a/src/armnn/ProfilingEvent.hpp b/src/armnn/ProfilingEvent.hpp
index 9f57753..7afd5c1 100644
--- a/src/armnn/ProfilingEvent.hpp
+++ b/src/armnn/ProfilingEvent.hpp
@@ -16,7 +16,7 @@
 {
 
 /// Forward declaration
-class Profiler;
+class IProfiler;
 
 /// Event class records measurements reported by BeginEvent()/EndEvent() and returns measurements when
 /// Event::GetMeasurements() is called.
@@ -27,7 +27,7 @@
     using Instruments = std::vector<InstrumentPtr>;
 
     Event(const std::string& eventName,
-          Profiler* profiler,
+          IProfiler* profiler,
           Event* parent,
           const BackendId backendId,
           std::vector<InstrumentPtr>&& instrument);
@@ -56,7 +56,7 @@
 
     /// Get the pointer of the profiler associated with this event
     /// \return Pointer of the profiler associated with this event
-    const Profiler* GetProfiler() const;
+    const IProfiler* GetProfiler() const;
 
     /// Get the pointer of the parent event
     /// \return Pointer of the parent event
@@ -77,7 +77,7 @@
     std::string m_EventName;
 
     /// Stored associated profiler
-    Profiler* m_Profiler;
+    IProfiler* m_Profiler;
 
     /// Stores optional parent event
     Event* m_Parent;
diff --git a/src/armnn/test/ProfilerTests.cpp b/src/armnn/test/ProfilerTests.cpp
index 7bd258e..a0df3b6 100644
--- a/src/armnn/test/ProfilerTests.cpp
+++ b/src/armnn/test/ProfilerTests.cpp
@@ -19,14 +19,14 @@
 namespace armnn
 {
 
-size_t GetProfilerEventSequenceSize(armnn::Profiler* profiler)
+size_t GetProfilerEventSequenceSize(armnn::IProfiler* profiler)
 {
     if (!profiler)
     {
         return static_cast<size_t>(-1);
     }
 
-    return profiler->m_EventSequence.size();
+    return profiler->pProfilerImpl->m_EventSequence.size();
 }
 } // namespace armnn
 
@@ -45,7 +45,7 @@
     res = !profilerManager.GetProfiler();
 
     // Create and register a profiler for this thread.
-    std::unique_ptr<armnn::Profiler> profiler = std::make_unique<armnn::Profiler>();
+    std::unique_ptr<armnn::IProfiler> profiler = std::make_unique<armnn::IProfiler>();
     profilerManager.RegisterProfiler(profiler.get());
 
     // Check that on a single thread we get the same profiler we registered.
@@ -66,7 +66,7 @@
 
 BOOST_AUTO_TEST_CASE(EnableDisableProfiling)
 {
-    std::unique_ptr<armnn::Profiler> profiler = std::make_unique<armnn::Profiler>();
+    std::unique_ptr<armnn::IProfiler> profiler = std::make_unique<armnn::IProfiler>();
 
     // Check that profiling is disabled by default.
     BOOST_TEST(!profiler->IsProfilingEnabled());
@@ -126,7 +126,7 @@
     }
 
     // Create and register a profiler for this thread.
-    std::unique_ptr<armnn::Profiler> profiler = std::make_unique<armnn::Profiler>();
+    std::unique_ptr<armnn::IProfiler> profiler = std::make_unique<armnn::IProfiler>();
     profilerManager.RegisterProfiler(profiler.get());
 
     { // --- Profiler, but profiling disabled ---
@@ -201,7 +201,7 @@
     armnn::ProfilerManager& profileManager = armnn::ProfilerManager::GetInstance();
 
     // Create and register a profiler for this thread.
-    std::unique_ptr<armnn::Profiler> profiler = std::make_unique<armnn::Profiler>();
+    std::unique_ptr<armnn::IProfiler> profiler = std::make_unique<armnn::IProfiler>();
     profileManager.RegisterProfiler(profiler.get());
 
     // Enable profiling.
@@ -282,7 +282,7 @@
     armnn::ProfilerManager& profilerManager = armnn::ProfilerManager::GetInstance();
 
     // Create and register a profiler for this thread.
-    std::unique_ptr<armnn::Profiler> profiler = std::make_unique<armnn::Profiler>();
+    std::unique_ptr<armnn::IProfiler> profiler = std::make_unique<armnn::IProfiler>();
     profilerManager.RegisterProfiler(profiler.get());
 
     profiler->EnableProfiling(true);
diff --git a/src/armnn/test/UnitTests.hpp b/src/armnn/test/UnitTests.hpp
index e0505c9..c15477b 100644
--- a/src/armnn/test/UnitTests.hpp
+++ b/src/armnn/test/UnitTests.hpp
@@ -64,7 +64,7 @@
 template<typename FactoryType, typename TFuncPtr, typename... Args>
 void RunTestFunction(const char* testName, TFuncPtr testFunction, Args... args)
 {
-    std::unique_ptr<armnn::Profiler> profiler = std::make_unique<armnn::Profiler>();
+    std::unique_ptr<armnn::IProfiler> profiler = std::make_unique<armnn::IProfiler>();
     armnn::ProfilerManager::GetInstance().RegisterProfiler(profiler.get());
 
     auto memoryManager = WorkloadFactoryHelper<FactoryType>::GetMemoryManager();
@@ -80,7 +80,7 @@
 template<typename FactoryType, typename TFuncPtr, typename... Args>
 void RunTestFunctionUsingTensorHandleFactory(const char* testName, TFuncPtr testFunction, Args... args)
 {
-    std::unique_ptr<armnn::Profiler> profiler = std::make_unique<armnn::Profiler>();
+    std::unique_ptr<armnn::IProfiler> profiler = std::make_unique<armnn::IProfiler>();
     armnn::ProfilerManager::GetInstance().RegisterProfiler(profiler.get());
 
     auto memoryManager = WorkloadFactoryHelper<FactoryType>::GetMemoryManager();
diff --git a/src/backends/backendsCommon/test/layerTests/DetectionPostProcessTestImpl.hpp b/src/backends/backendsCommon/test/layerTests/DetectionPostProcessTestImpl.hpp
index 34ff31e..3ee1fad 100644
--- a/src/backends/backendsCommon/test/layerTests/DetectionPostProcessTestImpl.hpp
+++ b/src/backends/backendsCommon/test/layerTests/DetectionPostProcessTestImpl.hpp
@@ -148,7 +148,7 @@
                               const std::vector<float>& expectedNumDetections,
                               bool useRegularNms)
 {
-    std::unique_ptr<armnn::Profiler> profiler = std::make_unique<armnn::Profiler>();
+    std::unique_ptr<armnn::IProfiler> profiler = std::make_unique<armnn::IProfiler>();
     armnn::ProfilerManager::GetInstance().RegisterProfiler(profiler.get());
 
     auto memoryManager = WorkloadFactoryHelper<FactoryType>::GetMemoryManager();
diff --git a/tests/InferenceTest.cpp b/tests/InferenceTest.cpp
index 3392f6e..e31e7dc 100644
--- a/tests/InferenceTest.cpp
+++ b/tests/InferenceTest.cpp
@@ -142,7 +142,7 @@
     }
 
     // Create a profiler and register it for the current thread.
-    std::unique_ptr<Profiler> profiler = std::make_unique<Profiler>();
+    std::unique_ptr<IProfiler> profiler = std::make_unique<IProfiler>();
     ProfilerManager::GetInstance().RegisterProfiler(profiler.get());
 
     // Enable profiling if requested.