diff --git a/Builds/VisualStudio2012/RippleD.vcxproj.filters b/Builds/VisualStudio2012/RippleD.vcxproj.filters
index 21784efacd..fd67ab9a46 100644
--- a/Builds/VisualStudio2012/RippleD.vcxproj.filters
+++ b/Builds/VisualStudio2012/RippleD.vcxproj.filters
@@ -1347,9 +1347,6 @@
[1] Ripple\ripple_app\_misc
-
- [1] Ripple\ripple_app\_misc
-
[1] Ripple\ripple_app\_misc
@@ -1533,6 +1530,9 @@
[1] Ripple\ripple_app\_transactions
+
+ [1] Ripple\ripple_app\_main
+
diff --git a/TODO.txt b/TODO.txt
index 3ac57e7186..b4dde7a2ea 100644
--- a/TODO.txt
+++ b/TODO.txt
@@ -31,6 +31,10 @@ WEBSOCKET TODO
RIPPLE TODO
--------------------------------------------------------------------------------
+- Remove dependence on JobQueue, LoadFeeTrack, and NetworkOPs from LoadManager
+ by providing an observer (beast::ListenerList or Listeners). This way
+ LoadManager does not need stopThread() function.
+
- Move everything in src/cpp/ripple into ripple_app and sort them into
subdirectories within the module as per the project filters.
* Make sure there are no pending commits from David
diff --git a/src/cpp/ripple/ripple_Application.cpp b/src/cpp/ripple/ripple_Application.cpp
index 2d8fdef005..f6e0997653 100644
--- a/src/cpp/ripple/ripple_Application.cpp
+++ b/src/cpp/ripple/ripple_Application.cpp
@@ -266,7 +266,20 @@ private:
};
Application::Application ()
+//
+// VFALCO NOTE Change this to control whether or not the Application
+// object is destroyed on exit
+//
+#if 1
+ // Application object will be deleted on exit. If the code doesn't exit
+ // cleanly this could cause hangs or crashes on exit.
+ //
: SharedSingleton (SingletonLifetime::persistAfterCreation)
+#else
+ // This will make it so that the Application object is not deleted on exit.
+ //
+ : SharedSingleton (SingletonLifetime::neverDestroyed)
+#endif
, mIOService ((theConfig.NODE_SIZE >= 2) ? 2 : 1)
, mIOWork (mIOService)
, mAuxWork (mAuxService)
@@ -308,6 +321,21 @@ Application::Application ()
HashMaps::getInstance ().initializeNonce ();
}
+Application::~Application ()
+{
+ // VFALCO TODO Wrap these in ScopedPointer
+ delete mTxnDB;
+ delete mLedgerDB;
+ delete mWalletDB;
+ delete mHashNodeDB;
+ delete mNetNodeDB;
+ delete mPathFindDB;
+ delete mHashNodeLDB;
+
+ if (mEphemeralLDB != nullptr)
+ delete mEphemeralLDB;
+}
+
// VFALCO TODO Tidy these up into some class with accessors.
//
extern const char* RpcDBInit[], *TxnDBInit[], *LedgerDBInit[], *WalletDBInit[], *HashNodeDBInit[],
@@ -666,10 +694,18 @@ void Application::run ()
if (mWSPrivateDoor)
mWSPrivateDoor->stop ();
- getApp().getLoadManager().stopThread();
+ // VFALCO TODO Try to not have to do this early, by using observers to
+ // eliminate LoadManager's dependency inversions.
+ //
+ // This deletes the object and therefore, stops the thread.
+ m_loadManager = nullptr;
+
mSweepTimer.cancel();
WriteLog (lsINFO, Application) << "Done.";
+
+ // VFALCO NOTE This is a sign that something is wrong somewhere, it
+ // shouldn't be necessary to sleep until some flag is set.
while (mShutdown)
boost::this_thread::sleep (boost::posix_time::milliseconds (100));
}
@@ -705,21 +741,6 @@ void Application::sweep ()
mSweepTimer.async_wait (BIND_TYPE (&Application::sweep, this));
}
-Application::~Application ()
-{
- // VFALCO TODO Wrap these in ScopedPointer
- delete mTxnDB;
- delete mLedgerDB;
- delete mWalletDB;
- delete mHashNodeDB;
- delete mNetNodeDB;
- delete mPathFindDB;
- delete mHashNodeLDB;
-
- if (mEphemeralLDB != nullptr)
- delete mEphemeralLDB;
-}
-
void Application::startNewLedger ()
{
// New stuff.
diff --git a/src/cpp/ripple/ripple_ILoadManager.h b/src/cpp/ripple/ripple_ILoadManager.h
index 002ad7814e..894f47c2f6 100644
--- a/src/cpp/ripple/ripple_ILoadManager.h
+++ b/src/cpp/ripple/ripple_ILoadManager.h
@@ -208,23 +208,27 @@ class ILoadManager
public:
/** Create a new manager.
+ The manager thread begins running immediately.
+
@note The thresholds for warnings and punishments are in
the ctor-initializer
*/
static ILoadManager* New ();
+ /** Destroy the manager.
+
+ The destructor returns only after the thread has stopped.
+ */
virtual ~ILoadManager () { }
/** Start the associated thread.
This is here to prevent the deadlock detector from activating during
a lengthy program initialization.
-
- @note In stand-alone mode, this might not get called.
*/
// VFALCO TODO Simplify the two stage initialization to one stage (construction).
+ // NOTE In stand-alone mode the load manager thread isn't started
virtual void startThread () = 0;
- virtual void stopThread () = 0;
/** Turn on deadlock detection.
diff --git a/src/cpp/ripple/ripple_LoadManager.cpp b/src/cpp/ripple/ripple_LoadManager.cpp
index 76163ad0d3..e9aefaf020 100644
--- a/src/cpp/ripple/ripple_LoadManager.cpp
+++ b/src/cpp/ripple/ripple_LoadManager.cpp
@@ -67,7 +67,6 @@ public:
, mDebitWarn (-500)
, mDebitLimit (-1000)
, mArmed (false)
- , mRunning (false)
, mDeadLock (0)
, mCosts (LT_MAX)
{
@@ -110,6 +109,8 @@ public:
addCost (Cost (LT_RequestData, -5, flagDisk | flagNet));
addCost (Cost (LT_CheapQuery, -1, flagCpu));
+
+ UptimeTimer::getInstance ().beginManualUpdates ();
}
private:
@@ -117,29 +118,12 @@ private:
{
UptimeTimer::getInstance ().endManualUpdates ();
- if (mRunning)
- {
- m_thread.interrupt ();
- m_thread.join ();
- }
+ m_thread.interrupt ();
}
void startThread ()
{
- UptimeTimer::getInstance ().beginManualUpdates ();
-
m_thread.start (this);
- mRunning = true;
- }
-
- void stopThread()
- {
- if (mRunning)
- {
- m_thread.interrupt ();
- m_thread.join ();
- mRunning = false;
- }
}
void canonicalize (LoadSource& source, int now) const
@@ -417,7 +401,7 @@ private:
int mDebitWarn; // when a source drops below this, we warn
int mDebitLimit; // when a source drops below this, we cut it off (should be negative)
- bool mArmed, mRunning;
+ bool mArmed;
int mDeadLock; // Detect server deadlocks