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