diff --git a/Builds/VisualStudio2013/RippleD.vcxproj b/Builds/VisualStudio2013/RippleD.vcxproj
index 067954d2be..a267e87dda 100644
--- a/Builds/VisualStudio2013/RippleD.vcxproj
+++ b/Builds/VisualStudio2013/RippleD.vcxproj
@@ -1682,6 +1682,11 @@
+
+ True
+
+
+
True
@@ -1783,11 +1788,6 @@
-
- True
-
-
-
True
diff --git a/Builds/VisualStudio2013/RippleD.vcxproj.filters b/Builds/VisualStudio2013/RippleD.vcxproj.filters
index b705c31a3e..a8f920bf23 100644
--- a/Builds/VisualStudio2013/RippleD.vcxproj.filters
+++ b/Builds/VisualStudio2013/RippleD.vcxproj.filters
@@ -295,6 +295,9 @@
{44B63F90-BC60-A7C7-24A1-632A358E285B}
+
+ {17F94278-7CDE-3EBE-7CD3-372F08902314}
+
{CE126498-A44D-30A2-345B-0F672BCDF947}
@@ -2544,6 +2547,12 @@
ripple\app\data
+
+ ripple\app\impl
+
+
+ ripple\app\impl
+
ripple\app\ledger
@@ -2667,12 +2676,6 @@
ripple\app\main
-
- ripple\app\main
-
-
- ripple\app\main
-
ripple\app\main
diff --git a/src/ripple/app/impl/BasicApp.cpp b/src/ripple/app/impl/BasicApp.cpp
new file mode 100644
index 0000000000..8e65069d02
--- /dev/null
+++ b/src/ripple/app/impl/BasicApp.cpp
@@ -0,0 +1,41 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of rippled: https://github.com/ripple/rippled
+ Copyright (c) 2012, 2013 Ripple Labs Inc.
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+#include
+
+BasicApp::BasicApp(std::size_t numberOfThreads)
+{
+ work_ = boost::in_place(std::ref(io_service_));
+ threads_.reserve(numberOfThreads);
+ while(numberOfThreads--)
+ threads_.emplace_back(
+ [this, numberOfThreads](){
+ beast::Thread::setCurrentThreadName(
+ std::string("io_service #") +
+ std::to_string(numberOfThreads));
+ this->io_service_.run();
+ });
+}
+
+BasicApp::~BasicApp()
+{
+ work_ = boost::none;
+ for (auto& _ : threads_)
+ _.join();
+}
diff --git a/src/ripple/app/main/IoServicePool.h b/src/ripple/app/impl/BasicApp.h
similarity index 57%
rename from src/ripple/app/main/IoServicePool.h
rename to src/ripple/app/impl/BasicApp.h
index c8cbf96d4f..06ca6906b5 100644
--- a/src/ripple/app/main/IoServicePool.h
+++ b/src/ripple/app/impl/BasicApp.h
@@ -17,44 +17,32 @@
*/
//==============================================================================
-#ifndef RIPPLE_APP_IOSERVICEPOOL_H_INCLUDED
-#define RIPPLE_APP_IOSERVICEPOOL_H_INCLUDED
+#ifndef RIPPLE_APP_BASICAPP_H_INCLUDED
+#define RIPPLE_APP_BASICAPP_H_INCLUDED
-#include
#include
#include
+#include
+#include
-#include
-
-namespace ripple {
-
-/** An io_service with an associated group of threads. */
-class IoServicePool : public beast::Stoppable
+// This is so that the io_service can outlive all the children
+class BasicApp
{
-public:
- IoServicePool (Stoppable& parent, std::string const& name, int numberOfThreads);
- ~IoServicePool ();
-
- boost::asio::io_service& getService ();
- operator boost::asio::io_service& ();
-
- void onStart ();
- void onStop ();
- void onChildrenStopped ();
-
private:
- class ServiceThread;
+ boost::optional work_;
+ std::vector threads_;
+ boost::asio::io_service io_service_;
- void onThreadExit();
+protected:
+ BasicApp(std::size_t numberOfThreads);
+ ~BasicApp();
- std::string m_name;
- boost::asio::io_service m_service;
- boost::optional m_work;
- std::vector > m_threads;
- int m_threadsDesired;
- std::atomic m_threadsRunning;
+public:
+ boost::asio::io_service&
+ get_io_service()
+ {
+ return io_service_;
+ }
};
-} // ripple
-
#endif
diff --git a/src/ripple/app/main/Application.cpp b/src/ripple/app/main/Application.cpp
index d837b7f932..7659e0fc67 100644
--- a/src/ripple/app/main/Application.cpp
+++ b/src/ripple/app/main/Application.cpp
@@ -17,13 +17,14 @@
*/
//==============================================================================
+#include
+#include
+#include
#include
#include
#include
#include
#include
-#include
-#include
#include
#include
#include
@@ -78,6 +79,7 @@ class ApplicationImp
, public beast::RootStoppable
, public beast::DeadlineTimer::Listener
, public beast::LeakChecked
+ , public BasicApp
{
private:
class io_latency_sampler
@@ -164,7 +166,6 @@ public:
// These are Stoppable-related
NodeStoreScheduler m_nodeStoreScheduler;
std::unique_ptr m_jobQueue;
- IoServicePool m_mainIoPool;
std::unique_ptr m_siteFiles;
std::unique_ptr m_rpcManager;
// VFALCO TODO Make OrderBookDB abstract
@@ -221,21 +222,21 @@ public:
return list;
}
- //--------------------------------------------------------------------------
-
static
- int
- calculateNumberOfIoServiceThreads()
+ std::size_t numberOfThreads()
{
#if RIPPLE_SINGLE_IO_SERVICE_THREAD
return 1;
#else
- return (getConfig ().NODE_SIZE >= 2) ? 2 : 1;
+ return (getConfig().NODE_SIZE >= 2) ? 2 : 1;
#endif
}
+ //--------------------------------------------------------------------------
+
ApplicationImp (Logs& logs)
: RootStoppable ("Application")
+ , BasicApp (numberOfThreads())
, m_logs (logs)
, m_journal (m_logs.journal("Application"))
@@ -271,11 +272,6 @@ public:
, m_jobQueue (make_JobQueue (m_collectorManager->group ("jobq"),
m_nodeStoreScheduler, m_logs.journal("JobQueue")))
- // The io_service must be a child of the JobQueue since we call addJob
- // in response to newtwork data from peers and also client requests.
- //
- , m_mainIoPool (*m_jobQueue, "io", calculateNumberOfIoServiceThreads())
-
//
// Anything which calls addJob must be a descendant of the JobQueue
//
@@ -344,10 +340,10 @@ public:
, mShutdown (false)
- , m_resolver (ResolverAsio::New (m_mainIoPool.getService (), beast::Journal ()))
+ , m_resolver (ResolverAsio::New (get_io_service(), beast::Journal ()))
, m_io_latency_sampler (m_collectorManager->collector()->make_event ("ios_latency"),
- m_logs.journal("Application"), std::chrono::milliseconds (100), m_mainIoPool.getService())
+ m_logs.journal("Application"), std::chrono::milliseconds (100), get_io_service())
{
add (m_resourceManager.get ());
@@ -412,7 +408,7 @@ public:
boost::asio::io_service& getIOService ()
{
- return m_mainIoPool;
+ return get_io_service();
}
std::chrono::milliseconds getIOLatency ()
@@ -718,10 +714,10 @@ public:
// move the instantiation inside a conditional:
//
// if (!getConfig ().RUN_STANDALONE)
- m_peers = make_Overlay (setup_Overlay(getConfig()), m_mainIoPool,
+ m_peers = make_Overlay (setup_Overlay(getConfig()), *m_jobQueue,
*m_resourceManager, *m_siteFiles,
getConfig().getModuleDatabasePath(), *m_resolver,
- m_mainIoPool);
+ get_io_service());
add (*m_peers); // add to PropertyStream
// SSL context used for WebSocket connections.
diff --git a/src/ripple/app/main/IoServicePool.cpp b/src/ripple/app/main/IoServicePool.cpp
deleted file mode 100644
index 6711e5dda4..0000000000
--- a/src/ripple/app/main/IoServicePool.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-//------------------------------------------------------------------------------
-/*
- This file is part of rippled: https://github.com/ripple/rippled
- Copyright (c) 2012, 2013 Ripple Labs Inc.
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-//==============================================================================
-
-#include
-#include
-#include //
-
-namespace ripple {
-
-class IoServicePool::ServiceThread : private beast::Thread
-{
-public:
- explicit ServiceThread (
- std::string const& name,
- IoServicePool& owner,
- boost::asio::io_service& service)
- : Thread (name)
- , m_owner (owner)
- , m_service (service)
- {
- startThread ();
- }
-
- ~ServiceThread ()
- {
- // block until thread exits
- stopThread ();
- }
-
- void start ()
- {
- startThread ();
- }
-
- void run ()
- {
- m_service.run ();
-
- m_owner.onThreadExit();
- }
-
-private:
- IoServicePool& m_owner;
- boost::asio::io_service& m_service;
-};
-
-//------------------------------------------------------------------------------
-
-IoServicePool::IoServicePool (Stoppable& parent, std::string const& name,
- int numberOfThreads)
- : Stoppable (name.c_str(), parent)
- , m_name (name)
- , m_service (numberOfThreads)
- , m_work (std::ref (m_service))
- , m_threadsDesired (numberOfThreads)
- , m_threadsRunning (0)
-{
- bassert (m_threadsDesired > 0);
-}
-
-IoServicePool::~IoServicePool ()
-{
- // the dtor of m_threads will block until each thread exits.
-}
-
-boost::asio::io_service& IoServicePool::getService ()
-{
- return m_service;
-}
-
-IoServicePool::operator boost::asio::io_service& ()
-{
- return m_service;
-}
-
-void IoServicePool::onStart ()
-{
- m_threads.reserve (m_threadsDesired);
- for (int i = 0; i < m_threadsDesired; ++i)
- {
- m_threads.emplace_back (std::move (std::make_unique <
- ServiceThread> (m_name, *this, m_service)));
- ++m_threadsRunning;
- m_threads[i]->start ();
- }
-}
-
-void IoServicePool::onStop ()
-{
- // VFALCO NOTE This is how it SHOULD work
- //
- //m_work = boost::none;
-}
-
-void IoServicePool::onChildrenStopped ()
-{
- // VFALCO NOTE This is a hack! We should gracefully
- // cancel all pending I/O, and delete the work
- // object using boost::optional, and let run()
- // just return naturally.
- //
- m_service.stop ();
-}
-
-// Called every time io_service::run() returns and a thread will exit.
-//
-void IoServicePool::onThreadExit()
-{
- // service must be stopping for threads to exit.
- bassert (isStopping());
-
- // must have at least count 1
- bassert (m_threadsRunning.load() > 0);
-
- if (--m_threadsRunning == 0)
- {
- // last thread just exited
- stopped ();
- }
-}
-
-} // ripple
diff --git a/src/ripple/unity/app.cpp b/src/ripple/unity/app.cpp
index e56bcc58a9..4d9e68f4c9 100644
--- a/src/ripple/unity/app.cpp
+++ b/src/ripple/unity/app.cpp
@@ -25,9 +25,9 @@
#include
#include
#include
+#include
#include
#include
-#include
#include
#include
#include