diff --git a/src/beast/Builds/VisualStudio2012/beast.vcxproj b/src/beast/Builds/VisualStudio2012/beast.vcxproj
index 9319d642ac..29ce253cfd 100644
--- a/src/beast/Builds/VisualStudio2012/beast.vcxproj
+++ b/src/beast/Builds/VisualStudio2012/beast.vcxproj
@@ -143,6 +143,7 @@
+
@@ -511,6 +512,12 @@
true
+
+ true
+ true
+ true
+ true
+ true
@@ -1482,6 +1489,8 @@
DisabledWIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)$(ProjectDir);%(AdditionalIncludeDirectories)
+ false
+ trueWindows
@@ -1510,6 +1519,8 @@
trueWIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)$(ProjectDir);%(AdditionalIncludeDirectories)
+ false
+ trueWindows
diff --git a/src/beast/Builds/VisualStudio2012/beast.vcxproj.filters b/src/beast/Builds/VisualStudio2012/beast.vcxproj.filters
index dffaf6ebb9..be1df3c138 100644
--- a/src/beast/Builds/VisualStudio2012/beast.vcxproj.filters
+++ b/src/beast/Builds/VisualStudio2012/beast.vcxproj.filters
@@ -303,6 +303,18 @@
{30b0fdfb-02b6-47dd-bdd9-ffc1f57e1f2c}
+
+ {9c1ef4c4-5623-4500-859f-12d6ce5ae362}
+
+
+ {fc3d3f14-9ba1-43e4-b086-cbbd2f63b944}
+
+
+ {44489531-f44a-439a-a6ea-d32c252b1e8b}
+
+
+ {df4f2935-13a1-4afe-90cc-d86472ec2466}
+
@@ -1263,6 +1275,9 @@
beast\crypto
+
+ beast\smart_ptr
+
@@ -1817,6 +1832,9 @@
beast\crypto\impl
+
+ beast\smart_ptr\impl
+
diff --git a/src/beast/beast/SmartPtr.h b/src/beast/beast/SmartPtr.h
index 13aab726a8..c73470b262 100644
--- a/src/beast/beast/SmartPtr.h
+++ b/src/beast/beast/SmartPtr.h
@@ -22,6 +22,7 @@
#include "Config.h"
+#include "smart_ptr/AbstractObject.h"
#include "smart_ptr/ContainerDeletePolicy.h"
#include "smart_ptr/SharedObject.h"
#include "smart_ptr/SharedPtr.h"
diff --git a/src/beast/beast/smart_ptr/AbstractObject.h b/src/beast/beast/smart_ptr/AbstractObject.h
new file mode 100644
index 0000000000..36c617847b
--- /dev/null
+++ b/src/beast/beast/smart_ptr/AbstractObject.h
@@ -0,0 +1,253 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Portions of this file are from JUCE.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+ Please visit http://www.juce.com
+
+ 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 BEAST_SMARTPTR_ABSTRACTOBJECT_H_INCLUDED
+#define BEAST_SMARTPTR_ABSTRACTOBJECT_H_INCLUDED
+
+#include
+#include
+#include
+#include "../Atomic.h"
+#include "../Config.h"
+#include "../Uncopyable.h"
+#include "../intrusive/LockFreeStack.h"
+#include "../smart_ptr/ScopedPointer.h"
+
+namespace beast {
+namespace abstract {
+
+/** Base for all abstract interfaces. */
+class BasicInterface
+{
+public:
+ virtual ~BasicInterface() { }
+
+ /** Returns the unique ID of this interface type.
+ The ID must be the same for all instances of the
+ derived interface.
+ */
+ virtual std::size_t id () const = 0;
+
+ /** Returns the unique ID associated with the Derived type. */
+ template
+ static std::size_t type_id ()
+ {
+ static std::size_t const value (next_id ());
+ return value;
+ }
+
+private:
+ // Returns a new unique id
+ static std::size_t next_id ()
+ {
+ static Atomic value;
+ return ++value;
+ }
+};
+
+//------------------------------------------------------------------------------
+
+/** Base for a derived interface. */
+template
+class Interface : public BasicInterface
+{
+public:
+ // Returns the unique ID for all instances of Derived
+ std::size_t id () const
+ {
+ return BasicInterface::type_id ();
+ }
+};
+
+//------------------------------------------------------------------------------
+
+/** Factory for producing interfaces on a specific object. */
+template
+class Factory
+{
+public:
+ class Callback;
+
+private:
+ struct Item;
+
+ typedef LockFreeStack Items;
+
+ struct Item : Items::Node
+ {
+ Item (Callback& owner_)
+ : owner (owner_)
+ { }
+ Callback& owner;
+ };
+
+ Items m_items;
+
+public:
+ /** Base for hooking object creation. */
+ class Callback
+ {
+ public:
+ /** Create the callback and insert it into the factory. */
+ explicit Callback (Factory& factory)
+ : m_item (*this)
+ {
+ factory.m_items.push_front (&m_item);
+ }
+
+ /** Called when Object is created.
+ Object must be fully constructed. The order of calls to callbacks
+ is not defined.
+ */
+ virtual void create_interfaces (Object& object) = 0;
+
+ private:
+ Item m_item;
+ };
+
+ /** Invokes the callbacks for an instance of Object.
+ This must be called after the object is fully constructed, for example
+ as the last statement in the constructor.
+ */
+ void create_interfaces (Object& object)
+ {
+ for (typename Items::iterator iter (m_items.begin());
+ iter != m_items.end(); ++iter)
+ iter->owner.create_interfaces (object);
+ }
+};
+
+//------------------------------------------------------------------------------
+
+/** A container of polymorphic interfaces.
+ The Object type associated with the container is used to gain access
+ to the corresponding factory.
+*/
+template
+class Interfaces : public Uncopyable
+{
+public:
+ Interfaces ()
+ {
+ }
+
+ /** Returns a reference to the specified interface.
+ The interface must exist in the container or an exception is thrown.
+ Requirements:
+ Derived must be a subclass of Interface
+ */
+ /** @{ */
+ template
+ Derived& get_interface()
+ {
+ Derived* derived (find_interface ());
+ if (derived == nullptr)
+ throw std::bad_cast ();
+ return *derived;
+ }
+
+ template
+ Derived const& get_interface() const
+ {
+ Derived const* derived (find_interface ());
+ if (derived == nullptr)
+ throw std::bad_cast ();
+ return *derived;
+ }
+ /** @} */
+
+ /** Returns a pointer to the specified interface.
+ If the interface does not exist, `nullptr` is returned.
+ Requirements:
+ Derived must be a subclass of Interface
+ */
+ /** @{ */
+ template
+ Derived* find_interface()
+ {
+ std::size_t const id = BasicInterface::type_id ();
+
+ for (typename Set::iterator iter (m_set.begin());
+ iter != m_set.end(); ++iter)
+ {
+ if ((*iter)->id() == id)
+ {
+ Derived* const derived (
+ dynamic_cast (iter->get()));
+ check_postcondition (derived != nullptr);
+ return derived;
+ }
+ }
+ return nullptr;
+ }
+
+ template
+ Derived const* find_interface() const
+ {
+ std::size_t const id = BasicInterface::type_id ();
+
+ for (typename Set::const_iterator iter (m_set.begin());
+ iter != m_set.end(); ++iter)
+ {
+ if ((*iter)->id() == id)
+ {
+ Derived const* const derived (
+ dynamic_cast (iter->get()));
+ check_postcondition (derived != nullptr);
+ return derived;
+ }
+ }
+ return nullptr;
+ }
+
+ template
+ bool has_interface() const
+ {
+ return find_interface () != nullptr;
+ }
+ /** @} */
+
+ /** Adds the specified interface to the container.
+ Ownership of the object, which must be allocated via operator new,
+ is transferred to the container. If the interface already exists,
+ an exception is thrown.
+ Requirements:
+ Derived must be a subclass of Interface
+ */
+ template
+ void add_interface (ScopedPointer && derived)
+ {
+ if (has_interface ())
+ throw std::invalid_argument ("non-unique");
+ m_set.emplace_back (derived);
+ }
+
+private:
+ typedef std::list > Set;
+ Set m_set;
+};
+
+}
+}
+
+#endif
diff --git a/src/beast/beast/smart_ptr/SmartPtr.cpp b/src/beast/beast/smart_ptr/SmartPtr.cpp
index 02700c5642..59a677e492 100644
--- a/src/beast/beast/smart_ptr/SmartPtr.cpp
+++ b/src/beast/beast/smart_ptr/SmartPtr.cpp
@@ -19,7 +19,13 @@
#include "BeastConfig.h"
+#include "../Config.h"
+
#include "ContainerDeletePolicy.h"
#include "ScopedPointer.h"
#include "SharedObject.h"
#include "SharedPtr.h"
+
+#include "../../modules/beast_core/beast_core.h" // for UnitTest
+
+#include "impl/AbstractObject.cpp"
diff --git a/src/beast/beast/smart_ptr/impl/AbstractObject.cpp b/src/beast/beast/smart_ptr/impl/AbstractObject.cpp
new file mode 100644
index 0000000000..f60e48b27d
--- /dev/null
+++ b/src/beast/beast/smart_ptr/impl/AbstractObject.cpp
@@ -0,0 +1,150 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Portions of this file are from JUCE.
+ Copyright (c) 2013 - Raw Material Software Ltd.
+ Please visit http://www.juce.com
+
+ 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 "../AbstractObject.h"
+
+namespace beast {
+namespace abstract {
+
+class AbstractObjectTests : public UnitTest
+{
+public:
+ class Object : public Interfaces