IVGCVSW-3964 Implement the Periodic Counter Selection command handler

 * Improved the PeriodicCounterPacket class to handle errors properly
 * Improved the PeriodicCounterSelectionCommandHandler to handle
   invalid counter UIDs in the selection packet
 * Added the Periodic Counter Selection command handler to the
   ProfilingService class
 * Code refactoring and added comments
 * Added WaitForPacketSent method to the SendCounterPacket class
   to allow waiting for the packets to be sent (useful in the
   unit tests)
 * Added unit tests and updated the old ones accordingly
 * Fixed threading issues with a number of unit tests

Signed-off-by: Matteo Martincigh <matteo.martincigh@arm.com>
Change-Id: I271b7b0bfa801d88fe1725b934d24e30cd839ed7
diff --git a/src/profiling/ProfilingService.cpp b/src/profiling/ProfilingService.cpp
index 693f833..7918441 100644
--- a/src/profiling/ProfilingService.cpp
+++ b/src/profiling/ProfilingService.cpp
@@ -53,6 +53,9 @@
         // Stop the send thread (if running)
         m_SendCounterPacket.Stop(false);
 
+        // Stop the periodic counter capture thread (if running)
+        m_PeriodicCounterCapture.Stop();
+
         // Reset any existing profiling connection
         m_ProfilingConnection.reset();
 
@@ -90,6 +93,9 @@
         break;
     case ProfilingState::Active:
 
+        // The period counter capture thread is started by the Periodic Counter Selection command handler upon
+        // request by an external profiling service
+
         break;
     default:
         throw RuntimeException(boost::str(boost::format("Unknown profiling service state: %1")
@@ -112,9 +118,14 @@
     return m_CounterDirectory.GetCounterCount();
 }
 
+bool ProfilingService::IsCounterRegistered(uint16_t counterUid) const
+{
+    return counterUid < m_CounterIndex.size();
+}
+
 uint32_t ProfilingService::GetCounterValue(uint16_t counterUid) const
 {
-    BOOST_ASSERT(counterUid < m_CounterIndex.size());
+    CheckCounterUid(counterUid);
     std::atomic<uint32_t>* counterValuePtr = m_CounterIndex.at(counterUid);
     BOOST_ASSERT(counterValuePtr);
     return counterValuePtr->load(std::memory_order::memory_order_relaxed);
@@ -122,7 +133,7 @@
 
 void ProfilingService::SetCounterValue(uint16_t counterUid, uint32_t value)
 {
-    BOOST_ASSERT(counterUid < m_CounterIndex.size());
+    CheckCounterUid(counterUid);
     std::atomic<uint32_t>* counterValuePtr = m_CounterIndex.at(counterUid);
     BOOST_ASSERT(counterValuePtr);
     counterValuePtr->store(value, std::memory_order::memory_order_relaxed);
@@ -130,7 +141,7 @@
 
 uint32_t ProfilingService::AddCounterValue(uint16_t counterUid, uint32_t value)
 {
-    BOOST_ASSERT(counterUid < m_CounterIndex.size());
+    CheckCounterUid(counterUid);
     std::atomic<uint32_t>* counterValuePtr = m_CounterIndex.at(counterUid);
     BOOST_ASSERT(counterValuePtr);
     return counterValuePtr->fetch_add(value, std::memory_order::memory_order_relaxed);
@@ -138,7 +149,7 @@
 
 uint32_t ProfilingService::SubtractCounterValue(uint16_t counterUid, uint32_t value)
 {
-    BOOST_ASSERT(counterUid < m_CounterIndex.size());
+    CheckCounterUid(counterUid);
     std::atomic<uint32_t>* counterValuePtr = m_CounterIndex.at(counterUid);
     BOOST_ASSERT(counterValuePtr);
     return counterValuePtr->fetch_sub(value, std::memory_order::memory_order_relaxed);
@@ -146,7 +157,7 @@
 
 uint32_t ProfilingService::IncrementCounterValue(uint16_t counterUid)
 {
-    BOOST_ASSERT(counterUid < m_CounterIndex.size());
+    CheckCounterUid(counterUid);
     std::atomic<uint32_t>* counterValuePtr = m_CounterIndex.at(counterUid);
     BOOST_ASSERT(counterValuePtr);
     return counterValuePtr->operator++(std::memory_order::memory_order_relaxed);
@@ -154,7 +165,7 @@
 
 uint32_t ProfilingService::DecrementCounterValue(uint16_t counterUid)
 {
-    BOOST_ASSERT(counterUid < m_CounterIndex.size());
+    CheckCounterUid(counterUid);
     std::atomic<uint32_t>* counterValuePtr = m_CounterIndex.at(counterUid);
     BOOST_ASSERT(counterValuePtr);
     return counterValuePtr->operator--(std::memory_order::memory_order_relaxed);
@@ -239,6 +250,7 @@
     // First stop the threads (Command Handler first)...
     m_CommandHandler.Stop();
     m_SendCounterPacket.Stop(false);
+    m_PeriodicCounterCapture.Stop();
 
     // ...then destroy the profiling connection...
     m_ProfilingConnection.reset();
@@ -252,6 +264,14 @@
     m_StateMachine.Reset();
 }
 
+inline void ProfilingService::CheckCounterUid(uint16_t counterUid) const
+{
+    if (!IsCounterRegistered(counterUid))
+    {
+        throw InvalidArgumentException(boost::str(boost::format("Counter UID %1% is not registered") % counterUid));
+    }
+}
+
 } // namespace profiling
 
 } // namespace armnn