mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-07 04:35:49 +00:00
Add AbstractObject
This commit is contained in:
@@ -143,6 +143,7 @@
|
||||
<ClInclude Include="..\..\beast\net\IPAddress.h" />
|
||||
<ClInclude Include="..\..\beast\SafeBool.h" />
|
||||
<ClInclude Include="..\..\beast\SmartPtr.h" />
|
||||
<ClInclude Include="..\..\beast\smart_ptr\AbstractObject.h" />
|
||||
<ClInclude Include="..\..\beast\smart_ptr\ContainerDeletePolicy.h" />
|
||||
<ClInclude Include="..\..\beast\smart_ptr\ScopedPointer.h" />
|
||||
<ClInclude Include="..\..\beast\smart_ptr\SharedObject.h" />
|
||||
@@ -511,6 +512,12 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\beast\net\Net.cpp" />
|
||||
<ClCompile Include="..\..\beast\smart_ptr\impl\AbstractObject.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\beast\smart_ptr\SmartPtr.cpp" />
|
||||
<ClCompile Include="..\..\beast\strings\impl\CharacterFunctions.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
@@ -1482,6 +1489,8 @@
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<DisableLanguageExtensions>false</DisableLanguageExtensions>
|
||||
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
@@ -1510,6 +1519,8 @@
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<DisableLanguageExtensions>false</DisableLanguageExtensions>
|
||||
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
|
||||
@@ -303,6 +303,18 @@
|
||||
<Filter Include="beast\asio\impl">
|
||||
<UniqueIdentifier>{30b0fdfb-02b6-47dd-bdd9-ffc1f57e1f2c}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="beast\http\crypto">
|
||||
<UniqueIdentifier>{9c1ef4c4-5623-4500-859f-12d6ce5ae362}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="beast\http\crypto\impl">
|
||||
<UniqueIdentifier>{fc3d3f14-9ba1-43e4-b086-cbbd2f63b944}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="beast\http\crypto\impl\sha2">
|
||||
<UniqueIdentifier>{44489531-f44a-439a-a6ea-d32c252b1e8b}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="beast\smart_ptr\impl">
|
||||
<UniqueIdentifier>{df4f2935-13a1-4afe-90cc-d86472ec2466}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\modules\beast_core\beast_core.h">
|
||||
@@ -1263,6 +1275,9 @@
|
||||
<ClInclude Include="..\..\beast\crypto\MurmurHash.h">
|
||||
<Filter>beast\crypto</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\beast\smart_ptr\AbstractObject.h">
|
||||
<Filter>beast\smart_ptr</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\modules\beast_core\containers\AbstractFifo.cpp">
|
||||
@@ -1817,6 +1832,9 @@
|
||||
<ClCompile Include="..\..\beast\crypto\impl\MurmurHash.cpp">
|
||||
<Filter>beast\crypto\impl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\beast\smart_ptr\impl\AbstractObject.cpp">
|
||||
<Filter>beast\smart_ptr\impl</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="..\..\TODO.txt">
|
||||
|
||||
@@ -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"
|
||||
|
||||
253
beast/smart_ptr/AbstractObject.h
Normal file
253
beast/smart_ptr/AbstractObject.h
Normal file
@@ -0,0 +1,253 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
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 <list>
|
||||
#include <stdexcept>
|
||||
#include <typeinfo>
|
||||
#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 <typename Derived>
|
||||
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 <std::size_t> value;
|
||||
return ++value;
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Base for a derived interface. */
|
||||
template <typename Derived>
|
||||
class Interface : public BasicInterface
|
||||
{
|
||||
public:
|
||||
// Returns the unique ID for all instances of Derived
|
||||
std::size_t id () const
|
||||
{
|
||||
return BasicInterface::type_id <Derived> ();
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Factory for producing interfaces on a specific object. */
|
||||
template <typename Object>
|
||||
class Factory
|
||||
{
|
||||
public:
|
||||
class Callback;
|
||||
|
||||
private:
|
||||
struct Item;
|
||||
|
||||
typedef LockFreeStack <Item> 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 <typename Object>
|
||||
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 <typename Derived>
|
||||
Derived& get_interface()
|
||||
{
|
||||
Derived* derived (find_interface <Derived> ());
|
||||
if (derived == nullptr)
|
||||
throw std::bad_cast ();
|
||||
return *derived;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
Derived const& get_interface() const
|
||||
{
|
||||
Derived const* derived (find_interface <Derived> ());
|
||||
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 <typename Derived>
|
||||
Derived* find_interface()
|
||||
{
|
||||
std::size_t const id = BasicInterface::type_id <Derived> ();
|
||||
|
||||
for (typename Set::iterator iter (m_set.begin());
|
||||
iter != m_set.end(); ++iter)
|
||||
{
|
||||
if ((*iter)->id() == id)
|
||||
{
|
||||
Derived* const derived (
|
||||
dynamic_cast <Derived*> (iter->get()));
|
||||
check_postcondition (derived != nullptr);
|
||||
return derived;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
Derived const* find_interface() const
|
||||
{
|
||||
std::size_t const id = BasicInterface::type_id <Derived> ();
|
||||
|
||||
for (typename Set::const_iterator iter (m_set.begin());
|
||||
iter != m_set.end(); ++iter)
|
||||
{
|
||||
if ((*iter)->id() == id)
|
||||
{
|
||||
Derived const* const derived (
|
||||
dynamic_cast <Derived const*> (iter->get()));
|
||||
check_postcondition (derived != nullptr);
|
||||
return derived;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool has_interface() const
|
||||
{
|
||||
return find_interface <Derived> () != 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 <typename Derived>
|
||||
void add_interface (ScopedPointer <Derived>&& derived)
|
||||
{
|
||||
if (has_interface <Derived> ())
|
||||
throw std::invalid_argument ("non-unique");
|
||||
m_set.emplace_back (derived);
|
||||
}
|
||||
|
||||
private:
|
||||
typedef std::list <ScopedPointer <BasicInterface>> Set;
|
||||
Set m_set;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -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"
|
||||
|
||||
150
beast/smart_ptr/impl/AbstractObject.cpp
Normal file
150
beast/smart_ptr/impl/AbstractObject.cpp
Normal file
@@ -0,0 +1,150 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
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 <Object>
|
||||
{
|
||||
public:
|
||||
explicit Object (UnitTest& test)
|
||||
: m_test (test)
|
||||
{
|
||||
}
|
||||
|
||||
UnitTest& test ()
|
||||
{
|
||||
return m_test;
|
||||
}
|
||||
|
||||
private:
|
||||
UnitTest& m_test;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
class Interface1 : public Interface <Interface1>
|
||||
{
|
||||
public:
|
||||
Interface1 ()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class Callback1 : public Factory <Object>::Callback
|
||||
{
|
||||
public:
|
||||
explicit Callback1 (Factory <Object>& factory)
|
||||
: Factory <Object>::Callback (factory)
|
||||
{
|
||||
}
|
||||
|
||||
void create_interfaces (Object& object)
|
||||
{
|
||||
object.add_interface (ScopedPointer <Interface1> (
|
||||
new Interface1));
|
||||
}
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
class Interface2 : public Interface <Interface2>
|
||||
{
|
||||
public:
|
||||
Interface2 ()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class Callback2 : public Factory <Object>::Callback
|
||||
{
|
||||
public:
|
||||
explicit Callback2 (Factory <Object>& factory)
|
||||
: Factory <Object>::Callback (factory)
|
||||
{
|
||||
}
|
||||
|
||||
void create_interfaces (Object& object)
|
||||
{
|
||||
object.add_interface (ScopedPointer <Interface2> (
|
||||
new Interface2));
|
||||
}
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void runTest ()
|
||||
{
|
||||
beginTestCase ("create");
|
||||
|
||||
Factory <Object> factory;
|
||||
Callback1 callback1 (factory);
|
||||
Callback2 callback2 (factory);
|
||||
|
||||
Object object (*this);
|
||||
factory.create_interfaces (object);
|
||||
|
||||
// find existing interfaces
|
||||
expect (object.find_interface <Interface1> () != nullptr);
|
||||
expect (object.find_interface <Interface2> () != nullptr);
|
||||
|
||||
// add duplicate interface
|
||||
try
|
||||
{
|
||||
object.add_interface (ScopedPointer <Interface1> (
|
||||
new Interface1));
|
||||
fail ("uncaught exeption");
|
||||
}
|
||||
catch (std::invalid_argument const&)
|
||||
{
|
||||
pass ();
|
||||
}
|
||||
|
||||
// request missing interface
|
||||
try
|
||||
{
|
||||
struct MissingInterface { };
|
||||
object.get_interface <MissingInterface> ();
|
||||
fail ("uncaught exeption");
|
||||
}
|
||||
catch (std::bad_cast const&)
|
||||
{
|
||||
pass ();
|
||||
}
|
||||
}
|
||||
|
||||
AbstractObjectTests () : UnitTest (
|
||||
"AbstractObject", "beast")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
static AbstractObjectTests abstractObjectTests;
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user