core: add a facility to execute functions on the main io_service

Change-Id: I38e5f4ad5ed6798a14e0075fb7a14b792f8b2413
refs: #4683
diff --git a/tests/core/global-io.t.cpp b/tests/core/global-io.t.cpp
index 8ae9126..5aa3bc6 100644
--- a/tests/core/global-io.t.cpp
+++ b/tests/core/global-io.t.cpp
@@ -51,20 +51,31 @@
   BOOST_CHECK(s1 != s2);
 }
 
-BOOST_FIXTURE_TEST_CASE(RibIoService, RibIoFixture)
+BOOST_FIXTURE_TEST_CASE(MainRibIoService, RibIoFixture)
 {
   boost::asio::io_service* mainIo = &g_io;
   boost::asio::io_service* ribIo = g_ribIo;
 
   BOOST_CHECK(mainIo != ribIo);
   BOOST_CHECK(&getGlobalIoService() == mainIo);
+  BOOST_CHECK(&getMainIoService() == mainIo);
   BOOST_CHECK(&getRibIoService() == ribIo);
   auto mainThreadId = boost::this_thread::get_id();
 
   runOnRibIoService([&] {
     BOOST_CHECK(mainThreadId != boost::this_thread::get_id());
-    BOOST_CHECK(&getRibIoService() == ribIo);
     BOOST_CHECK(&getGlobalIoService() == ribIo);
+    BOOST_CHECK(&getMainIoService() == mainIo);
+    BOOST_CHECK(&getRibIoService() == ribIo);
+  });
+
+  runOnRibIoService([&] {
+    runOnMainIoService([&] {
+      BOOST_CHECK(mainThreadId == boost::this_thread::get_id());
+      BOOST_CHECK(&getGlobalIoService() == mainIo);
+      BOOST_CHECK(&getMainIoService() == mainIo);
+      BOOST_CHECK(&getRibIoService() == ribIo);
+    });
   });
 }
 
@@ -80,10 +91,10 @@
 
   hasRibRun = false;
   bool hasMainRun = false;
-  g_io.post([&] {
-      hasMainRun = true;
-      runOnRibIoService([&] { hasRibRun = true; });
-    });
+  runOnMainIoService([&] {
+    hasMainRun = true;
+    runOnRibIoService([&] { hasRibRun = true; });
+  });
   BOOST_CHECK_EQUAL(hasMainRun, false);
   BOOST_CHECK_EQUAL(hasRibRun, false);
 
@@ -105,9 +116,9 @@
   hasRibRun = false;
   bool hasMainRun = false;
   scheduler::schedule(250_ms, [&] {
-      hasMainRun = true;
-      runOnRibIoService([&] { hasRibRun = true; });
-    });
+    hasMainRun = true;
+    runOnRibIoService([&] { hasRibRun = true; });
+  });
   BOOST_CHECK_EQUAL(hasMainRun, false);
   BOOST_CHECK_EQUAL(hasRibRun, false);
 
diff --git a/tests/rib-io-fixture.cpp b/tests/rib-io-fixture.cpp
index ef228d5..d058851 100644
--- a/tests/rib-io-fixture.cpp
+++ b/tests/rib-io-fixture.cpp
@@ -35,6 +35,9 @@
   std::mutex m;
   std::condition_variable cv;
 
+  g_mainIo = &getGlobalIoService();
+  setMainIoService(g_mainIo);
+
   g_ribThread = boost::thread([&] {
     {
       std::lock_guard<std::mutex> lock(m);
diff --git a/tests/rib-io-fixture.hpp b/tests/rib-io-fixture.hpp
index e89ba44..ec147d5 100644
--- a/tests/rib-io-fixture.hpp
+++ b/tests/rib-io-fixture.hpp
@@ -56,6 +56,10 @@
   poll();
 
 protected:
+  /** \brief pointer to global main io_service
+   */
+  boost::asio::io_service* g_mainIo = nullptr;
+
   /** \brief pointer to global RIB io_service
    */
   boost::asio::io_service* g_ribIo = nullptr;