diff --git a/Builds/QtCreator/rippled.pro b/Builds/QtCreator/rippled.pro
index 8c921b682..40cf9912f 100644
--- a/Builds/QtCreator/rippled.pro
+++ b/Builds/QtCreator/rippled.pro
@@ -65,6 +65,7 @@ UI_HEADERS_DIR += ../../src/ripple_basics
SOURCES += \
../../src/ripple/beast/ripple_beast.cpp \
../../src/ripple/beast/ripple_beastc.c \
+ ../../src/ripple/common/ripple_common.cpp \
../../src/ripple/http/ripple_http.cpp \
../../src/ripple/json/ripple_json.cpp \
../../src/ripple/peerfinder/ripple_peerfinder.cpp \
diff --git a/Builds/VisualStudio2012/RippleD.vcxproj b/Builds/VisualStudio2012/RippleD.vcxproj
index 2500709e5..f2097bbc2 100644
--- a/Builds/VisualStudio2012/RippleD.vcxproj
+++ b/Builds/VisualStudio2012/RippleD.vcxproj
@@ -22,6 +22,13 @@
+
+ true
+ true
+ true
+ true
+
+
true
true
@@ -1532,6 +1539,12 @@
true
true
+
+ true
+ true
+ true
+ true
+
true
true
@@ -2128,6 +2141,7 @@
+
@@ -2487,6 +2501,7 @@
+
diff --git a/Builds/VisualStudio2012/RippleD.vcxproj.filters b/Builds/VisualStudio2012/RippleD.vcxproj.filters
index 2fb26387d..e5df7b624 100644
--- a/Builds/VisualStudio2012/RippleD.vcxproj.filters
+++ b/Builds/VisualStudio2012/RippleD.vcxproj.filters
@@ -289,6 +289,15 @@
{013f0eb9-bf1d-4b11-8c2c-3fd99d4b8ef5}
+
+ {b99052d6-a903-4dfd-9c68-ff767a7d8f63}
+
+
+ {70365f6a-d1e6-45f2-a064-0e842b0fdd78}
+
+
+ {9b8137bd-737d-4825-98bf-897a0635293a}
+
@@ -1401,8 +1410,14 @@
[1] Ripple\types\impl
-
- [1] Ripple\types\impl
+
+ [1] Ripple\common
+
+
+ [1] Ripple\common\functional\impl
+
+
+ [2] Old Ripple\ripple_core\nodestore\backend
@@ -2880,6 +2895,12 @@
[1] Ripple\types\api
+
+ [1] Ripple\common\functional
+
+
+ [2] Old Ripple\ripple_core\nodestore\backend
+
diff --git a/SConstruct b/SConstruct
index f31e45b99..4d22c1869 100644
--- a/SConstruct
+++ b/SConstruct
@@ -156,6 +156,7 @@ COMPILED_FILES.extend (['src/ripple/beast/ripple_beastc.c'])
# New-style Ripple unity sources
#
COMPILED_FILES.extend([
+ 'src/ripple/common/ripple_common.cpp',
'src/ripple/http/ripple_http.cpp',
'src/ripple/json/ripple_json.cpp',
'src/ripple/peerfinder/ripple_peerfinder.cpp',
diff --git a/src/ripple/common/functional/counted_bind.h b/src/ripple/common/functional/counted_bind.h
new file mode 100644
index 000000000..9dd6b881d
--- /dev/null
+++ b/src/ripple/common/functional/counted_bind.h
@@ -0,0 +1,241 @@
+//------------------------------------------------------------------------------
+/*
+ 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.
+*/
+//==============================================================================
+
+#ifndef RIPPLE_COUNTED_BIND_H_INCLUDED
+#define RIPPLE_COUNTED_BIND_H_INCLUDED
+
+#include
+#include
+#include
+
+namespace ripple {
+
+namespace detail {
+
+// Wrapper for managing the handler count
+template
+class counted_bind_wrapper
+{
+public:
+ template
+ counted_bind_wrapper (H&& h, Counter& c)
+ : m_handler (std::forward (h))
+ , m_counter (c)
+ {
+ ++m_counter;
+ }
+
+ counted_bind_wrapper (counted_bind_wrapper&& w)
+ : m_handler (std::move (w.m_handler))
+ , m_counter (w.m_counter)
+ {
+ ++m_counter;
+ }
+
+ counted_bind_wrapper (counted_bind_wrapper const& w)
+ : m_handler (w.m_handler)
+ , m_counter (w.m_counter)
+ {
+ ++m_counter;
+ }
+
+ ~counted_bind_wrapper ()
+ {
+ --m_counter;
+ }
+
+ //counted_bind_wrapper& operator= (counted_bind_wrapper const&) = delete;
+
+#if 0
+ // When variadic template arguments are supported
+ template
+ void operator () (Args&& ...args) const
+ {
+ m_handler (std::forward (args)...);
+ }
+
+#else
+ void operator() ()
+ {
+ m_handler ();
+ }
+
+ void operator() () const
+ {
+ m_handler ();
+ }
+
+ template
+ void operator() (P1 const& p1)
+ {
+ m_handler (p1);
+ }
+
+ template
+ void operator() (P1 const& p1) const
+ {
+ m_handler (p1);
+ }
+
+ template
+ void operator() (P1 const& p1, P2 const& p2)
+ {
+ m_handler (p1, p2);
+ }
+
+ template
+ void operator() (P1 const& p1, P2 const& p2) const
+ {
+ m_handler (p1, p2);
+ }
+
+ template
+ void operator() (P1 const& p1, P2 const& p2, P3 const& p3)
+ {
+ m_handler (p1, p2, p3);
+ }
+
+ template
+ void operator() (P1 const& p1, P2 const& p2, P3 const& p3) const
+ {
+ m_handler (p1, p2, p3);
+ }
+
+ template
+ void operator() (P1 const& p1, P2 const& p2, P3 const& p3, P4 const& p4)
+ {
+ m_handler (p1, p2, p3, p4);
+ }
+
+ template
+ void operator() (P1 const& p1, P2 const& p2, P3 const& p3, P4 const& p4) const
+ {
+ m_handler (p1, p2, p3, p4);
+ }
+
+ template
+ void operator() (P1 const& p1, P2 const& p2, P3 const& p3, P4 const& p4,
+ P5 const& p5)
+ {
+ m_handler (p1, p2, p3, p4, p5);
+ }
+
+ template
+ void operator() (P1 const& p1, P2 const& p2, P3 const& p3, P4 const& p4,
+ P5 const& p5) const
+ {
+ m_handler (p1, p2, p3, p4, p5);
+ }
+
+ template
+ void operator() (P1 const& p1, P2 const& p2, P3 const& p3, P4 const& p4,
+ P5 const& p5, P6 const& p6)
+ {
+ m_handler (p1, p2, p3, p4, p5, p6);
+ }
+
+ template
+ void operator() (P1 const& p1, P2 const& p2, P3 const& p3, P4 const& p4,
+ P5 const& p5, P6 const& p6) const
+ {
+ m_handler (p1, p2, p3, p4, p5, p6);
+ }
+
+ template
+ void operator() (P1 const& p1, P2 const& p2, P3 const& p3, P4 const& p4,
+ P5 const& p5, P6 const& p6, P7 const& p7)
+ {
+ m_handler (p1, p2, p3, p4, p5, p6, p7);
+ }
+
+ template
+ void operator() (P1 const& p1, P2 const& p2, P3 const& p3, P4 const& p4,
+ P5 const& p5, P6 const& p6, P7 const& p7) const
+ {
+ m_handler (p1, p2, p3, p4, p5, p6, p7);
+ }
+
+ template
+ void operator() (P1 const& p1, P2 const& p2, P3 const& p3, P4 const& p4,
+ P5 const& p5, P6 const& p6, P7 const& p7, P8 const& p8)
+ {
+ m_handler (p1, p2, p3, p4, p5, p6, p7, p8);
+ }
+
+ template
+ void operator() (P1 const& p1, P2 const& p2, P3 const& p3, P4 const& p4,
+ P5 const& p5, P6 const& p6, P7 const& p7, P8 const& p8) const
+ {
+ m_handler (p1, p2, p3, p4, p5, p6, p7, p8);
+ }
+
+#endif
+
+private:
+ Handler m_handler;
+ Counter& m_counter;
+};
+
+}
+
+//------------------------------------------------------------------------------
+
+/** Provides a counted_bind replacement for bind which counts pending I/Os.
+ Derive your class from this class and then call the bind member
+ function instead.
+*/
+class enable_counted_bind
+{
+public:
+ typedef std::size_t size_type;
+
+private:
+ typedef std::atomic counter_type;
+
+public:
+ enable_counted_bind ()
+ : m_count (0)
+ {
+ }
+
+ /** Return the number of binds pending completion. */
+ size_type bind_count () const
+ {
+ return m_count.load ();
+ }
+
+ /** Returns a wrapper that calls the handler and manages the counter. */
+ template
+ detail::counted_bind_wrapper wrap (Handler&& h)
+ {
+ return detail::counted_bind_wrapper (
+ std::forward (h), m_count);
+ }
+
+private:
+ counter_type m_count;
+};
+
+}
+
+#endif
diff --git a/src/ripple/common/functional/impl/counted_bind.cpp b/src/ripple/common/functional/impl/counted_bind.cpp
new file mode 100644
index 000000000..9ebcc718f
--- /dev/null
+++ b/src/ripple/common/functional/impl/counted_bind.cpp
@@ -0,0 +1,176 @@
+//------------------------------------------------------------------------------
+/*
+ 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 "../counted_bind.h"
+
+namespace ripple {
+
+using namespace beast;
+
+class TrackedHandler
+{
+public:
+ explicit TrackedHandler (Journal journal)
+ : m_journal (journal)
+ {
+ m_journal.info << "Constructor";
+ }
+
+ TrackedHandler (TrackedHandler const& h)
+ : m_journal (h.m_journal)
+ {
+ m_journal.info << "Copy Constructor";
+ }
+
+ TrackedHandler (TrackedHandler&& h)
+ : m_journal (std::move (h.m_journal))
+ {
+ m_journal.info << "Move Constructor";
+ }
+
+ // VFALCO NOTE What the heck does this do?
+ TrackedHandler (TrackedHandler const&& h)
+ : m_journal (h.m_journal)
+ {
+ m_journal.info << "Move Constructor (const)";
+ }
+
+ ~TrackedHandler ()
+ {
+ m_journal.info << "Destructor";
+ }
+
+ void operator () () const
+ {
+ m_journal.info << "Function call";
+ }
+
+private:
+ Journal m_journal;
+};
+
+//------------------------------------------------------------------------------
+
+template
+struct HandlerWrapper
+{
+#if 1
+ // Universal constructor
+ template
+ HandlerWrapper (H&& h, std::nullptr_t) // dummy arg
+ : m_handler (std::forward (h))
+ {
+ }
+
+#else
+ // move construct
+ HandlerWrapper (Handler&& h, nullptr_t)
+ : m_handler (std::move (h))
+ {
+ }
+
+ // copy construct
+ HandlerWrapper (Handler const& h, nullptr_t)
+ : m_handler (h)
+ {
+ }
+#endif
+
+#if 0
+ template
+ void operator () (Args&& ...args)
+ {
+ m_handler (std::forward (args)...);
+ }
+
+#else
+ void operator() () const
+ {
+ m_handler ();
+ }
+
+#endif
+
+ Handler const m_handler;
+};
+
+template
+HandlerWrapper <
+ typename std::remove_reference ::type> make_handler (Handler&& h)
+{
+ typedef typename std::remove_reference ::type handler_type;
+ return HandlerWrapper (
+ std::forward (h), nullptr);
+}
+
+//------------------------------------------------------------------------------
+
+class CountedBindTests : public UnitTest
+{
+public:
+ void runTest ()
+ {
+ beginTestCase ("Move");
+
+ Journal const j (journal());
+
+ {
+ j.info << "w1";
+ TrackedHandler h (j);
+ HandlerWrapper w1 (std::move (h), nullptr);
+ w1 ();
+ }
+
+ {
+ j.info << "w2";
+ HandlerWrapper w2 ((TrackedHandler (j)), nullptr);
+ w2 ();
+ }
+
+ {
+ j.info << "w3";
+ TrackedHandler const h (j);
+ HandlerWrapper w3 (h, nullptr);
+ w3 ();
+ }
+
+ {
+ j.info << "w4";
+ auto w4 (make_handler (TrackedHandler (j)));
+ w4 ();
+ }
+
+ {
+ j.info << "w5";
+ TrackedHandler const h (j);
+ auto w5 (make_handler (h));
+ w5 ();
+ }
+
+ pass ();
+ }
+
+ CountedBindTests () : UnitTest ("counted_bind", "ripple", runManual)
+ {
+ }
+};
+
+static CountedBindTests countedBindTests;
+
+}
diff --git a/src/ripple/common/ripple_common.cpp b/src/ripple/common/ripple_common.cpp
new file mode 100644
index 000000000..1d1795d32
--- /dev/null
+++ b/src/ripple/common/ripple_common.cpp
@@ -0,0 +1,24 @@
+//------------------------------------------------------------------------------
+/*
+ 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 "BeastConfig.h"
+
+#include "../../beast/modules/beast_core/beast_core.h" // for UnitTest
+
+#include "functional/impl/counted_bind.cpp"