Remove multithreaded code, and make crow use a single thread

Change-Id: I39e9ba84ab3464cf75b5bba82badb729525bf3b9
Signed-off-by: Ed Tanous <ed.tanous@intel.com>
diff --git a/crow/include/crow/app.h b/crow/include/crow/app.h
index c43faf3..be5523e 100644
--- a/crow/include/crow/app.h
+++ b/crow/include/crow/app.h
@@ -69,18 +69,6 @@
     return *this;
   }
 
-  self_t& multithreaded() {
-    return concurrency(std::thread::hardware_concurrency());
-  }
-
-  self_t& concurrency(std::uint16_t concurrency) {
-    if (concurrency < 1) {
-      concurrency = 1;
-    }
-    concurrency_ = concurrency;
-    return *this;
-  }
-
   void validate() { router_.validate(); }
 
   void run() {
@@ -88,13 +76,11 @@
 #ifdef CROW_ENABLE_SSL
     if (use_ssl_) {
       if (-1 == socket_) {
-        ssl_server_ = std::move(
-          std::make_unique<ssl_server_t>(this, bindaddr_, port_, &middlewares_,
-                                         concurrency_, &ssl_context_, io_));
+        ssl_server_ = std::move(std::make_unique<ssl_server_t>(
+            this, bindaddr_, port_, &middlewares_, &ssl_context_, io_));
       } else {
-        ssl_server_ = std::move(
-          std::make_unique<ssl_server_t>(this, socket_, &middlewares_,
-                                         concurrency_, &ssl_context_, io_));
+        ssl_server_ = std::move(std::make_unique<ssl_server_t>(
+            this, socket_, &middlewares_, &ssl_context_, io_));
       }
       ssl_server_->set_tick_function(tick_interval_, tick_function_);
       ssl_server_->run();
@@ -103,30 +89,17 @@
     {
       if (-1 == socket_) {
         server_ = std::move(std::make_unique<server_t>(
-            this, bindaddr_, port_, &middlewares_, concurrency_, nullptr, io_));
+            this, bindaddr_, port_, &middlewares_, nullptr, io_));
       } else {
         server_ = std::move(std::make_unique<server_t>(
-            this, socket_, &middlewares_, concurrency_, nullptr, io_));
+            this, socket_, &middlewares_, nullptr, io_));
       }
       server_->set_tick_function(tick_interval_, tick_function_);
       server_->run();
     }
   }
 
-  void stop() {
-#ifdef CROW_ENABLE_SSL
-    if (use_ssl_) {
-      if (ssl_server_ != nullptr) {
-        ssl_server_->stop();
-      }
-    } else
-#endif
-    {
-      if (server_ != nullptr) {
-        server_->stop();
-      }
-    }
-  }
+  void stop() { io_->stop(); }
 
   void debug_print() {
     CROW_LOG_DEBUG << "Routing:";
@@ -221,7 +194,6 @@
  private:
   std::shared_ptr<asio::io_service> io_;
   uint16_t port_ = 80;
-  uint16_t concurrency_ = 1;
   std::string bindaddr_ = "::";
   int socket_ = -1;
   Router router_;
diff --git a/crow/include/crow/http_server.h b/crow/include/crow/http_server.h
index 387d4a4..e770195 100644
--- a/crow/include/crow/http_server.h
+++ b/crow/include/crow/http_server.h
@@ -26,7 +26,6 @@
  public:
   Server(Handler* handler, std::unique_ptr<tcp::acceptor>&& acceptor,
          std::tuple<Middlewares...>* middlewares = nullptr,
-         uint16_t concurrency = 1,
          typename Adaptor::context* adaptor_ctx = nullptr,
          std::shared_ptr<boost::asio::io_service> io =
              std::make_shared<boost::asio::io_service>())
@@ -35,33 +34,30 @@
         signals_(*io_service_, SIGINT, SIGTERM),
         tick_timer_(*io_service_),
         handler_(handler),
-        concurrency_(concurrency),
         middlewares_(middlewares),
         adaptor_ctx_(adaptor_ctx) {}
 
   Server(Handler* handler, const std::string& bindaddr, uint16_t port,
          std::tuple<Middlewares...>* middlewares = nullptr,
-         uint16_t concurrency = 1,
          typename Adaptor::context* adaptor_ctx = nullptr,
          std::shared_ptr<boost::asio::io_service> io =
              std::make_shared<boost::asio::io_service>())
       : Server(handler,
-          std::make_unique<tcp::acceptor>(
-            *io, tcp::endpoint(
-              boost::asio::ip::address::from_string(bindaddr), port)),
-          middlewares, concurrency, adaptor_ctx, io) {}
-
+               std::make_unique<tcp::acceptor>(
+                   *io,
+                   tcp::endpoint(
+                       boost::asio::ip::address::from_string(bindaddr), port)),
+               middlewares, adaptor_ctx, io) {}
 
   Server(Handler* handler, int existing_socket,
          std::tuple<Middlewares...>* middlewares = nullptr,
-         uint16_t concurrency = 1,
          typename Adaptor::context* adaptor_ctx = nullptr,
          std::shared_ptr<boost::asio::io_service> io =
              std::make_shared<boost::asio::io_service>())
       : Server(handler,
-          std::make_unique<tcp::acceptor>(
-            *io, boost::asio::ip::tcp::v6(), existing_socket),
-          middlewares, concurrency, adaptor_ctx, io) {}
+               std::make_unique<tcp::acceptor>(*io, boost::asio::ip::tcp::v6(),
+                                               existing_socket),
+               middlewares, adaptor_ctx, io) {}
 
   void set_tick_function(std::chrono::milliseconds d, std::function<void()> f) {
     tick_interval_ = d;
@@ -80,81 +76,49 @@
     });
   }
 
-  void run() {
-    if (concurrency_ < 0) {
-      concurrency_ = 1;
-    }
-
-    for (int i = 0; i < concurrency_; i++) {
-      io_service_pool_.emplace_back(new boost::asio::io_service());
-    }
-    get_cached_date_str_pool_.resize(concurrency_);
-    timer_queue_pool_.resize(concurrency_);
-
-    std::vector<std::future<void>> v;
-    std::atomic<int> init_count(0);
-    for (uint16_t i = 0; i < concurrency_; i++) {
-      v.push_back(std::async(std::launch::async, [this, i, &init_count] {
-
-        // thread local date string get function
-        auto last = std::chrono::steady_clock::now();
-
-        std::string date_str;
-        auto update_date_str = [&] {
-          auto last_time_t = time(0);
-          tm my_tm{};
+  void update_date_str() {
+    auto last_time_t = time(0);
+    tm my_tm{};
 
 #ifdef _MSC_VER
-          gmtime_s(&my_tm, &last_time_t);
+    gmtime_s(&my_tm, &last_time_t);
 #else
-          gmtime_r(&last_time_t, &my_tm);
+    gmtime_r(&last_time_t, &my_tm);
 #endif
-          date_str.resize(100);
-          size_t date_str_sz =
-              strftime(&date_str[0], 99, "%a, %d %b %Y %H:%M:%S GMT", &my_tm);
-          date_str.resize(date_str_sz);
-        };
+    date_str.resize(100);
+    size_t date_str_sz =
+        strftime(&date_str[0], 99, "%a, %d %b %Y %H:%M:%S GMT", &my_tm);
+    date_str.resize(date_str_sz);
+  };
+
+  void run() {
+    update_date_str();
+
+    get_cached_date_str_ = [this]() -> std::string {
+      static std::chrono::time_point<std::chrono::steady_clock>
+          last_date_update = std::chrono::steady_clock::now();
+      if (std::chrono::steady_clock::now() - last_date_update >=
+          std::chrono::seconds(10)) {
+        last_date_update = std::chrono::steady_clock::now();
         update_date_str();
-        get_cached_date_str_pool_[i] = [&]() -> std::string {
-          if (std::chrono::steady_clock::now() - last >=
-              std::chrono::seconds(1)) {
-            last = std::chrono::steady_clock::now();
-            update_date_str();
-          }
-          return date_str;
-        };
+      }
+      return this->date_str;
+    };
 
-        // initializing timer queue
-        detail::dumb_timer_queue timer_queue;
-        timer_queue_pool_[i] = &timer_queue;
+    timer_queue_.set_io_service(*io_service_);
+    boost::asio::deadline_timer timer(*io_service_);
+    timer.expires_from_now(boost::posix_time::seconds(1));
 
-        timer_queue.set_io_service(*io_service_pool_[i]);
-        boost::asio::deadline_timer timer(*io_service_pool_[i]);
-        timer.expires_from_now(boost::posix_time::seconds(1));
-
-        std::function<void(const boost::system::error_code& ec)> handler;
-        handler = [&](const boost::system::error_code& ec) {
-          if (ec != nullptr) {
-            return;
-          }
-          timer_queue.process();
-          timer.expires_from_now(boost::posix_time::seconds(1));
-          timer.async_wait(handler);
-        };
-        timer.async_wait(handler);
-        init_count++;
-        for (;;) {
-          try {
-            io_service_pool_[i]->run();
-            break;
-          } catch (std::exception& e) {
-            std::cerr << "Worker Crash: An uncaught exception occurred: "
-                      << e.what();
-          } catch (...) {
-          }
-        }
-      }));
-    }
+    std::function<void(const boost::system::error_code& ec)> handler;
+    handler = [&](const boost::system::error_code& ec) {
+      if (ec != nullptr) {
+        return;
+      }
+      timer_queue_.process();
+      timer.expires_from_now(boost::posix_time::seconds(1));
+      timer.async_wait(handler);
+    };
+    timer.async_wait(handler);
 
     if (tick_function_ && tick_interval_.count() > 0) {
       tick_timer_.expires_from_now(
@@ -173,63 +137,38 @@
     signals_.async_wait([&](const boost::system::error_code& /*error*/,
                             int /*signal_number*/) { stop(); });
 
-    while (concurrency_ != init_count) {
-      std::this_thread::yield();
-    }
-
     do_accept();
-
-    io_service_->run();
-    CROW_LOG_INFO << "Exiting.";
   }
 
-  void stop() {
-    io_service_->stop();
-    for (auto& io_service : io_service_pool_) {
-      io_service->stop();
-    }
-  }
-
- private:
-  asio::io_service& pick_io_service() {
-    // TODO load balancing
-    roundrobin_index_++;
-    if (roundrobin_index_ >= io_service_pool_.size()) {
-      roundrobin_index_ = 0;
-    }
-    return *io_service_pool_[roundrobin_index_];
-  }
+  void stop() { io_service_->stop(); }
 
   void do_accept() {
-    asio::io_service& is = pick_io_service();
     auto p = new Connection<Adaptor, Handler, Middlewares...>(
-        is, handler_, server_name_, middlewares_,
-        get_cached_date_str_pool_[roundrobin_index_],
-        *timer_queue_pool_[roundrobin_index_], adaptor_ctx_);
+        *io_service_, handler_, server_name_, middlewares_,
+        get_cached_date_str_, timer_queue_, adaptor_ctx_);
     acceptor_->async_accept(p->socket(),
-                           [this, p, &is](boost::system::error_code ec) {
-                             if (!ec) {
-                               is.post([p] { p->start(); });
-                             } else {
-                               delete p;
-                             }
-                             do_accept();
-                           });
+                            [this, p](boost::system::error_code ec) {
+                              if (!ec) {
+                                this->io_service_->post([p] { p->start(); });
+                              } else {
+                                delete p;
+                              }
+                              do_accept();
+                            });
   }
 
  private:
   std::shared_ptr<asio::io_service> io_service_;
-  std::vector<std::unique_ptr<asio::io_service>> io_service_pool_;
-  std::vector<detail::dumb_timer_queue*> timer_queue_pool_;
-  std::vector<std::function<std::string()>> get_cached_date_str_pool_;
+  detail::dumb_timer_queue timer_queue_;
+  std::function<std::string()> get_cached_date_str_;
   std::unique_ptr<tcp::acceptor> acceptor_;
   boost::asio::signal_set signals_;
   boost::asio::deadline_timer tick_timer_;
 
+  std::string date_str;
+
   Handler* handler_;
-  uint16_t concurrency_{1};
   std::string server_name_ = "iBMC";
-  unsigned int roundrobin_index_{};
 
   std::chrono::milliseconds tick_interval_{};
   std::function<void()> tick_function_;
@@ -241,5 +180,5 @@
   boost::asio::ssl::context ssl_context_{boost::asio::ssl::context::sslv23};
 #endif
   typename Adaptor::context* adaptor_ctx_;
-};
+};  // namespace crow
 }  // namespace crow
diff --git a/src/webserver_main.cpp b/src/webserver_main.cpp
index 53dd127..b84c94c 100644
--- a/src/webserver_main.cpp
+++ b/src/webserver_main.cpp
@@ -1,3 +1,4 @@
+#include <systemd/sd-daemon.h>
 #include <dbus/connection.hpp>
 #include <dbus_monitor.hpp>
 #include <dbus_singleton.hpp>
@@ -16,7 +17,6 @@
 #include "webserver_common.hpp"
 #include <crow/app.h>
 #include <boost/asio.hpp>
-#include <systemd/sd-daemon.h>
 
 constexpr int defaultPort = 18080;
 
@@ -31,7 +31,7 @@
       app.socket(SD_LISTEN_FDS_START);
     } else {
       CROW_LOG_INFO << "bad incoming socket, starting webserver on port "
-                << defaultPort;
+                    << defaultPort;
       app.port(defaultPort);
     }
   } else {
@@ -78,4 +78,5 @@
   redfish::RedfishService redfish(app);
 
   app.run();
+  io->run();
 }