Add manager class to run the server and video

Change-Id: Ie69e995dd56f8d2aa7e3828504e29f9993bb2b3c
Signed-off-by: Eddie James <eajames@linux.ibm.com>
diff --git a/Makefile.am b/Makefile.am
index e3bb48a..58e53fb 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -3,12 +3,14 @@
 noinst_HEADERS = \
 	ikvm_args.hpp \
 	ikvm_input.hpp \
+	ikvm_manager.hpp \
 	ikvm_server.hpp \
 	ikvm_video.hpp
 
 obmc_ikvm_SOURCES = \
 	ikvm_args.cpp \
 	ikvm_input.cpp \
+	ikvm_manager.cpp \
 	ikvm_server.cpp \
 	ikvm_video.cpp \
 	obmc-ikvm.cpp
diff --git a/ikvm_manager.cpp b/ikvm_manager.cpp
new file mode 100644
index 0000000..90a9fce
--- /dev/null
+++ b/ikvm_manager.cpp
@@ -0,0 +1,100 @@
+#include "ikvm_manager.hpp"
+
+#include <thread>
+
+namespace ikvm
+{
+
+Manager::Manager(const Args& args) :
+    continueExecuting(true), serverDone(false), videoDone(true),
+    input(args.getInputPath()),
+    video(args.getVideoPath(), input, args.getFrameRate()),
+    server(args, input, video)
+{
+}
+
+void Manager::run()
+{
+    std::thread run(serverThread, this);
+
+    while (continueExecuting)
+    {
+        if (server.wantsFrame())
+        {
+            video.getFrame();
+            server.sendFrame();
+        }
+        else
+        {
+            video.stop();
+        }
+
+        if (video.needsResize())
+        {
+            videoDone = false;
+            waitServer();
+            video.resize();
+            server.resize();
+            setVideoDone();
+        }
+        else
+        {
+            setVideoDone();
+            waitServer();
+        }
+    }
+
+    run.join();
+}
+
+void Manager::serverThread(Manager* manager)
+{
+    while (manager->continueExecuting)
+    {
+        manager->server.run();
+        manager->setServerDone();
+        manager->waitVideo();
+    }
+}
+
+void Manager::setServerDone()
+{
+    std::unique_lock<std::mutex> ulock(lock);
+
+    serverDone = true;
+    sync.notify_all();
+}
+
+void Manager::setVideoDone()
+{
+    std::unique_lock<std::mutex> ulock(lock);
+
+    videoDone = true;
+    sync.notify_all();
+}
+
+void Manager::waitServer()
+{
+    std::unique_lock<std::mutex> ulock(lock);
+
+    while (!serverDone)
+    {
+        sync.wait(ulock);
+    }
+
+    serverDone = false;
+}
+
+void Manager::waitVideo()
+{
+    std::unique_lock<std::mutex> ulock(lock);
+
+    while (!videoDone)
+    {
+        sync.wait(ulock);
+    }
+
+    // don't reset videoDone
+}
+
+} // namespace ikvm
diff --git a/ikvm_manager.hpp b/ikvm_manager.hpp
new file mode 100644
index 0000000..67d5a68
--- /dev/null
+++ b/ikvm_manager.hpp
@@ -0,0 +1,75 @@
+#pragma once
+
+#include "ikvm_args.hpp"
+#include "ikvm_input.hpp"
+#include "ikvm_server.hpp"
+#include "ikvm_video.hpp"
+
+#include <condition_variable>
+#include <mutex>
+
+namespace ikvm
+{
+
+/*
+ * @class Manager
+ * @brief Manages the VNC server by executing threaded loops of RFB operations
+ *        and video device operations.
+ */
+class Manager
+{
+  public:
+    /*
+     * @brief Constructs the Manager object
+     *
+     * @param[in] args - Reference to Args object
+     */
+    Manager(const Args& args);
+    ~Manager() = default;
+    Manager(const Manager&) = default;
+    Manager& operator=(const Manager&) = default;
+    Manager(Manager&&) = default;
+    Manager& operator=(Manager&&) = default;
+
+    /* @brief Begins operation of the VNC server */
+    void run();
+
+  private:
+    /*
+     * @brief Thread function to loop the RFB update operations
+     *
+     * @param[in] manager - Pointer to the Manager object
+     */
+    static void serverThread(Manager* manager);
+
+    /* @brief Notifies thread waiters that RFB operations are complete */
+    void setServerDone();
+    /* @brief Notifies thread waiters that video operations are complete */
+    void setVideoDone();
+    /* @brief Blocks until RFB operations complete */
+    void waitServer();
+    /* @brief Blocks until video operations are complete */
+    void waitVideo();
+
+    /*
+     * @brief Boolean to indicate whether the application should continue
+     *        running
+     */
+    bool continueExecuting;
+    /* @brief Boolean to indicate that RFB operations are complete */
+    bool serverDone;
+    /* @brief Boolean to indicate that video operations are complete */
+    bool videoDone;
+    /* @brief Input object */
+    Input input;
+    /* @brief Video object */
+    Video video;
+    /* @brief RFB server object */
+    Server server;
+    /* @brief Condition variable to enable waiting for thread completion */
+    std::condition_variable sync;
+    /* @brief Mutex for waiting on condition variable safely */
+    std::mutex lock;
+};
+
+} // namespace ikvm
diff --git a/obmc-ikvm.cpp b/obmc-ikvm.cpp
index fa413c1..271857b 100644
--- a/obmc-ikvm.cpp
+++ b/obmc-ikvm.cpp
@@ -1,8 +1,12 @@
 #include "ikvm_args.hpp"
+#include "ikvm_manager.hpp"
 
 int main(int argc, char* argv[])
 {
     ikvm::Args args(argc, argv);
+    ikvm::Manager manager(args);
+
+    manager.run();
 
     return 0;
 }