replace tuple-based singleton with individual singletons

The tuple-based singletons did not actually enforce singleton behavior
and the requirement of the accessor mechanism to include all of the
member types at once was starting to cause a header prerequisite
tangle. This removes the cross-dependencies and enforces actual
singletons by making a single way to access the class.

Tested: Run ipmitool to show that behavior has not changed

Change-Id: Ie966e1142363d279365b1095066380c8383e9f9b
Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
diff --git a/sol/sol_context.cpp b/sol/sol_context.cpp
index 3b2b892..f0e036c 100644
--- a/sol/sol_context.cpp
+++ b/sol/sol_context.cpp
@@ -1,7 +1,9 @@
 #include "sol_context.hpp"
 
 #include "main.hpp"
+#include "message_handler.hpp"
 #include "sd_event_loop.hpp"
+#include "sessions_manager.hpp"
 #include "sol_manager.hpp"
 
 #include <phosphor-logging/log.hpp>
@@ -18,7 +20,7 @@
     sendThreshold(sendThreshold), payloadInstance(instance),
     sessionID(sessionID)
 {
-    session = std::get<session::Manager&>(singletonPool).getSession(sessionID);
+    session = session::Manager::get().getSession(sessionID);
 }
 
 std::shared_ptr<Context>
@@ -35,8 +37,7 @@
 void Context::enableAccumulateTimer(bool enable)
 {
     // fetch the timeout from the SOL manager
-    std::chrono::microseconds interval =
-        std::get<sol::Manager&>(singletonPool).accumulateInterval;
+    std::chrono::microseconds interval = sol::Manager::get().accumulateInterval;
     if (enable)
     {
         accumulateTimer.expires_after(interval);
@@ -61,8 +62,7 @@
     if (enable)
     {
         // fetch the timeout from the SOL manager
-        std::chrono::microseconds interval =
-            std::get<sol::Manager&>(singletonPool).retryInterval;
+        std::chrono::microseconds interval = sol::Manager::get().retryInterval;
         retryTimer.expires_after(interval);
         std::weak_ptr<Context> weakRef = weak_from_this();
         retryTimer.async_wait([weakRef](const boost::system::error_code& ec) {
@@ -133,7 +133,7 @@
     else if ((count == expectedCharCount) && ackSeqNum)
     {
         // Clear the Host Console Buffer
-        std::get<sol::Manager&>(singletonPool).dataBuffer.erase(count);
+        sol::Manager::get().dataBuffer.erase(count);
 
         // Once it is acknowledged stop the retry interval timer
         enableRetryTimer(false);
@@ -146,8 +146,7 @@
     // Write character data to the Host Console
     if (!input.empty() && seqNum)
     {
-        auto rc =
-            std::get<sol::Manager&>(singletonPool).writeConsoleSocket(input);
+        auto rc = sol::Manager::get().writeConsoleSocket(input);
         if (rc)
         {
             log<level::ERR>("Writing to console socket descriptor failed");
@@ -182,7 +181,7 @@
 
 void Context::prepareResponse(uint8_t ackSeqNum, uint8_t count, bool ack)
 {
-    auto bufferSize = std::get<sol::Manager&>(singletonPool).dataBuffer.size();
+    auto bufferSize = sol::Manager::get().dataBuffer.size();
 
     /* Sent a ACK only response */
     if (payloadCache.size() != 0 || (bufferSize < sendThreshold))
@@ -207,7 +206,7 @@
     response->outOperation.ack = ack;
     response->packetSeqNum = seqNums.incOutboundSeqNum();
 
-    auto handle = std::get<sol::Manager&>(singletonPool).dataBuffer.read();
+    auto handle = sol::Manager::get().dataBuffer.read();
     std::copy_n(handle, readSize, payloadCache.data() + sizeof(Payload));
     expectedCharCount = readSize;
 
@@ -225,7 +224,7 @@
         return -1;
     }
 
-    auto bufferSize = std::get<sol::Manager&>(singletonPool).dataBuffer.size();
+    auto bufferSize = sol::Manager::get().dataBuffer.size();
     auto readSize = std::min(bufferSize, MAX_PAYLOAD_SIZE);
 
     payloadCache.resize(sizeof(Payload) + readSize);
@@ -235,7 +234,7 @@
     response->outOperation.ack = false;
     response->packetSeqNum = seqNums.incOutboundSeqNum();
 
-    auto handle = std::get<sol::Manager&>(singletonPool).dataBuffer.read();
+    auto handle = sol::Manager::get().dataBuffer.read();
     std::copy_n(handle, readSize, payloadCache.data() + sizeof(Payload));
     expectedCharCount = readSize;
 
@@ -255,8 +254,7 @@
     {
         payloadCache.clear();
         expectedCharCount = 0;
-        std::get<sol::Manager&>(singletonPool)
-            .dataBuffer.erase(expectedCharCount);
+        sol::Manager::get().dataBuffer.erase(expectedCharCount);
     }
 }
 
@@ -269,7 +267,7 @@
 
 void Context::charAccTimerHandler()
 {
-    auto bufferSize = std::get<sol::Manager&>(singletonPool).dataBuffer.size();
+    auto bufferSize = sol::Manager::get().dataBuffer.size();
 
     try
     {
diff --git a/sol/sol_manager.cpp b/sol/sol_manager.cpp
index 8407292..2102032 100644
--- a/sol/sol_manager.cpp
+++ b/sol/sol_manager.cpp
@@ -255,8 +255,7 @@
                         if (state != nullptr && *state == false)
                         {
                             // Stop all the payload session.
-                            std::get<sol::Manager&>(singletonPool)
-                                .stopAllPayloadInstance();
+                            sol::Manager::get().stopAllPayloadInstance();
                         }
                     }
                 });
diff --git a/sol/sol_manager.hpp b/sol/sol_manager.hpp
index 4e797d4..b266519 100644
--- a/sol/sol_manager.hpp
+++ b/sol/sol_manager.hpp
@@ -1,6 +1,7 @@
 #pragma once
 
 #include "console_buffer.hpp"
+#include "main.hpp"
 #include "session.hpp"
 #include "sol_context.hpp"
 
@@ -36,6 +37,11 @@
  */
 class Manager
 {
+  private:
+    struct Private
+    {
+    };
+
   public:
     /** @brief SOL Payload Instance is the key for the map, the value is the
      *         SOL context.
@@ -49,10 +55,27 @@
     Manager(Manager&&) = default;
     Manager& operator=(Manager&&) = default;
 
-    Manager(std::shared_ptr<boost::asio::io_context> io) : io(io)
+    Manager(std::shared_ptr<boost::asio::io_context>& io, const Private&) :
+        io(io)
     {
     }
 
+    /**
+     * @brief Get a reference to the singleton Manager
+     *
+     * @return Manager reference
+     */
+    static Manager& get()
+    {
+        static std::shared_ptr<Manager> ptr = nullptr;
+        if (!ptr)
+        {
+            std::shared_ptr<boost::asio::io_context> io = getIo();
+            ptr = std::make_shared<Manager>(io, Private());
+        }
+        return *ptr;
+    }
+
     /** @brief io context to add events to */
     std::shared_ptr<boost::asio::io_context> io;