Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changing authority of Optional/Required Addons #607

Merged
merged 3 commits into from
Mar 18, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions dart/common/Addon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,6 @@ const Addon::Properties* Addon::getAddonProperties() const
return nullptr;
}

//==============================================================================
bool Addon::isOptional(AddonManager* /*oldManager*/)
{
return true;
}

//==============================================================================
Addon::Addon(AddonManager* manager)
{
Expand Down
13 changes: 0 additions & 13 deletions dart/common/Addon.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,19 +111,6 @@ class Addon
/// which implies that the Addon has no properties.
virtual const Properties* getAddonProperties() const;

/// This function will be called if the user is attempting to delete the Addon
/// but not immediately replacing it with another Addon of the same type. The
/// incoming argument will point to the AddonManager that had been holding
/// this Addon.
///
/// If your Addon is mandatory for the AddonManager type that is passed in
/// here, then you should perform error handling in this function, and you
/// should return false to indicate that the operation is not permitted. If
/// you return false, then the Addon will NOT be removed from its Manager.
///
/// By default, this simply returns true.
virtual bool isOptional(AddonManager* oldManager);

protected:

/// Constructor
Expand Down
43 changes: 22 additions & 21 deletions dart/common/AddonManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#define DART_COMMON_ADDONMANAGER_H_

#include <map>
#include <unordered_set>
#include <typeinfo>
#include <typeindex>

Expand All @@ -54,27 +55,8 @@ namespace common {
/// on average in log(N) time. Most often, a class that accepts Addons will have
/// certain Addon types that it will need to access frequently, and it would be
/// beneficial to have constant-time access to those Addon types. To get
/// constant-time access to specific Addon types, there are FOUR macros that you
/// should use in your derived class:
///
/// DART_ENABLE_ADDON_SPECIALIZATION() must be declared once in the derived
/// class's definition, under a 'public:' declaration range.
///
/// DART_SPECIALIZE_ADDON_INTERNAL( AddonType ) must be declared once for each
/// AddonType that you want to specialize. It should be placed in the derived
/// class's definition, under a 'public:' declaration range.
///
/// DART_SPECIALIZE_ADDON_EXTERNAL( Derived, AddonType ) must be declared once
/// for each AddonType that you want to specialize. It should be placed
/// immediately after the class's definition in the same header file as the
/// derived class, inside of the same namespace as the derived class. This macro
/// defines a series of templated functions, so it should go in a header, and
/// not in a source file.
///
/// DART_INSTANTIATE_SPECIALIZED_ADDON( AddonType ) must be declared once for
/// each AddonType that you want to specialize. It should be placed inside the
/// constructor of the derived class, preferably before anything else is done
/// inside the body of the constructor.
/// constant-time access to specific Addon types, you can use the templated
/// class SpecializedForAddon.
class AddonManager
{
public:
Expand All @@ -86,10 +68,21 @@ class AddonManager
using Properties = ExtensibleMapHolder<PropertiesMap>;

using AddonMap = std::map< std::type_index, std::unique_ptr<Addon> >;
using RequiredAddonSet = std::unordered_set<std::type_index>;

/// Virtual destructor
virtual ~AddonManager() = default;

/// Default constructor
AddonManager() = default;

/// It is currently unsafe to copy an AddonManager
// TODO(MXG): Consider making this safe by cloning Addons into the new copy
AddonManager(const AddonManager&) = delete;

/// It is currently unsafe to move an AddonManager
AddonManager(AddonManager&&) = delete;

/// Check if this AddonManager currently has a certain type of Addon
template <class T>
bool has() const;
Expand Down Expand Up @@ -134,6 +127,10 @@ class AddonManager
template <class T>
static constexpr bool isSpecializedFor();

/// Check if this Manager requires this specific type of Addon
template <class T>
bool requires() const;

/// Set the states of the addons in this AddonManager based on the given
/// AddonManager::State. The states of any Addon types that do not exist
/// within this manager will be ignored.
Expand Down Expand Up @@ -175,6 +172,10 @@ class AddonManager

/// A map that relates the type of Addon to its pointer
AddonMap mAddonMap;

/// A set containing type information for Addons which are not allowed to
/// leave this manager.
RequiredAddonSet mRequiredAddons;
};

} // namespace common
Expand Down
4 changes: 2 additions & 2 deletions dart/common/AddonManagerJoiner.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ template <class Base1>
class AddonManagerJoiner<Base1> : public Base1 { };

/// AddonManagerJoiner allows classes that inherit from various
/// SpecializedAddonManager types to be inherited by a single derived class.
/// SpecializedForAddon types to be inherited by a single derived class.
/// This class solves the diamond-of-death problem for multiple
/// SpecializedAddonManager inheritance.
/// SpecializedForAddon inheritance.
template <class Base1, class Base2>
class AddonManagerJoiner<Base1, Base2> : public Base1, public Base2
{
Expand Down
77 changes: 77 additions & 0 deletions dart/common/RequiresAddon.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* Copyright (c) 2016, Georgia Tech Research Corporation
* All rights reserved.
*
* Author(s): Michael X. Grey <[email protected]>
*
* Georgia Tech Graphics Lab and Humanoid Robotics Lab
*
* Directed by Prof. C. Karen Liu and Prof. Mike Stilman
* <[email protected]> <[email protected]>
*
* This file is provided under the following "BSD-style" License:
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef DART_COMMON_REQUIRESADDON_H_
#define DART_COMMON_REQUIRESADDON_H_

#include "dart/common/SpecializedForAddon.h"

namespace dart {
namespace common {

//==============================================================================
/// RequiresAddon allows classes that inherit AddonManager to know which Addons
/// are required for their operation. This guarantees that there is no way for
/// a required Addon do not get unexpectedly removed from their manager.
///
/// Required Addons are also automatically specialized for.
template <class... OtherRequiredAddons>
class RequiresAddon { };

//==============================================================================
template <class ReqAddon>
class RequiresAddon<ReqAddon> : public virtual SpecializedForAddon<ReqAddon>
{
public:

/// Default constructor. This is where the base AddonManager is informed that
/// the Addon type is required.
RequiresAddon();

};

//==============================================================================
template <class ReqAddon1, class... OtherReqAddons>
class RequiresAddon<ReqAddon1, OtherReqAddons...> :
public AddonManagerJoiner< Virtual< RequiresAddon<ReqAddon1> >,
Virtual< RequiresAddon<OtherReqAddons...> > > { };

} // namespace common
} // namespace dart

#include "dart/common/detail/RequiresAddon.h"

#endif // DART_COMMON_REQUIRESADDON_H_
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,18 @@ namespace common {

/// Declaration of the variadic template
template <class... OtherSpecAddons>
class SpecializedAddonManager { };
class SpecializedForAddon { };

//==============================================================================
/// SpecializedAddonManager allows classes that inherit AddonManager to have
/// SpecializedForAddon allows classes that inherit AddonManager to have
/// constant-time access to a specific type of Addon
template <class SpecAddon>
class SpecializedAddonManager<SpecAddon> : public virtual AddonManager
class SpecializedForAddon<SpecAddon> : public virtual AddonManager
{
public:

/// Default Constructor
SpecializedAddonManager();
SpecializedForAddon();

/// Check if this AddonManager currently has a certain type of Addon
template <class T>
Expand Down Expand Up @@ -173,23 +173,23 @@ class SpecializedAddonManager<SpecAddon> : public virtual AddonManager
/// Return true
static constexpr bool _isSpecializedFor(type<SpecAddon>);

/// Iterator that points to the Addon of this SpecializedAddonManager
/// Iterator that points to the Addon of this SpecializedForAddon
AddonManager::AddonMap::iterator mSpecAddonIterator;

};

//==============================================================================
/// This is the variadic version of the SpecializedAddonManager class which
/// This is the variadic version of the SpecializedForAddon class which
/// allows you to include arbitrarily many specialized types in the
/// specialization.
template <class SpecAddon1, class... OtherSpecAddons>
class SpecializedAddonManager<SpecAddon1, OtherSpecAddons...> :
public AddonManagerJoiner< Virtual< SpecializedAddonManager<SpecAddon1> >,
Virtual< SpecializedAddonManager<OtherSpecAddons...> > > { };
class SpecializedForAddon<SpecAddon1, OtherSpecAddons...> :
public AddonManagerJoiner< Virtual< SpecializedForAddon<SpecAddon1> >,
Virtual< SpecializedForAddon<OtherSpecAddons...> > > { };

} // namespace common
} // namespace dart

#include "dart/common/detail/SpecializedAddonManager.h"
#include "dart/common/detail/SpecializedForAddon.h"

#endif // DART_COMMON_SPECIALIZEDADDONMANAGER_H_
34 changes: 21 additions & 13 deletions dart/common/detail/AddonManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,11 @@

#include "dart/common/AddonManager.h"

#define DART_COMMON_CHECK_ILLEGAL_ADDON_ERASE( Func, it, ReturnType )\
if(it ->second && !it ->second->isOptional(this))\
#define DART_COMMON_CHECK_ILLEGAL_ADDON_ERASE( Func, T, ReturnType )\
if(requires< T >())\
{\
dterr << "[AddonManager::" #Func << "] Illegal request to remove Addon!\n";\
dterr << "[AddonManager::" #Func << "] Illegal request to remove required "\
<< "Addon [" << typeid(T).name() << "]!\n";\
assert(false);\
return ReturnType ;\
}
Expand Down Expand Up @@ -114,7 +115,7 @@ template <class T>
void AddonManager::erase()
{
AddonMap::iterator it = mAddonMap.find( typeid(T) );
DART_COMMON_CHECK_ILLEGAL_ADDON_ERASE(erase, it, DART_BLANK)
DART_COMMON_CHECK_ILLEGAL_ADDON_ERASE(erase, T, DART_BLANK)
if(mAddonMap.end() != it)
it->second = nullptr;
}
Expand All @@ -125,7 +126,7 @@ std::unique_ptr<T> AddonManager::release()
{
std::unique_ptr<T> extraction = nullptr;
AddonMap::iterator it = mAddonMap.find( typeid(T) );
DART_COMMON_CHECK_ILLEGAL_ADDON_ERASE(release, it, nullptr)
DART_COMMON_CHECK_ILLEGAL_ADDON_ERASE(release, T, nullptr)
if(mAddonMap.end() != it)
extraction = std::unique_ptr<T>(static_cast<T*>(it->second.release()));

Expand All @@ -139,29 +140,36 @@ constexpr bool AddonManager::isSpecializedFor()
return false;
}

//==============================================================================
template <class T>
bool AddonManager::requires() const
{
return (mRequiredAddons.find(typeid(T)) != mRequiredAddons.end());
}

} // namespace common
} // namespace dart

//==============================================================================
// Create non-template alternatives to AddonManager functions
#define DART_BAKE_SPECIALIZED_ADDON_IRREGULAR( TypeName, AddonName )\
inline bool has ## AddonName () const\
{ return has<TypeName>(); }\
{ return this->template has<TypeName>(); }\
inline TypeName * get ## AddonName ()\
{ return get<TypeName>(); }\
{ return this->template get<TypeName>(); }\
inline const TypeName* get ## AddonName () const\
{ return get<TypeName>(); }\
{ return this->template get<TypeName>(); }\
inline void set ## AddonName (const TypeName * addon)\
{ set<TypeName>(addon); }\
{ this->template set<TypeName>(addon); }\
inline void set ## AddonName (std::unique_ptr< TypeName >&& addon)\
{ set<TypeName>(std::move(addon)); }\
{ this->template set<TypeName>(std::move(addon)); }\
template <typename ...Args>\
inline TypeName * create ## AddonName (Args&&... args)\
{ return create<TypeName>(std::forward<Args>(args)...); }\
{ return this->template create<TypeName>(std::forward<Args>(args)...); }\
inline void erase ## AddonName ()\
{ erase<TypeName>(); }\
{ this->template erase<TypeName>(); }\
inline std::unique_ptr< TypeName > release ## AddonName ()\
{ return release<TypeName>(); }
{ return this->template release<TypeName>(); }

//==============================================================================
#define DART_BAKE_SPECIALIZED_ADDON(AddonName)\
Expand Down
55 changes: 55 additions & 0 deletions dart/common/detail/RequiresAddon.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright (c) 2016, Georgia Tech Research Corporation
* All rights reserved.
*
* Author(s): Michael X. Grey <[email protected]>
*
* Georgia Tech Graphics Lab and Humanoid Robotics Lab
*
* Directed by Prof. C. Karen Liu and Prof. Mike Stilman
* <[email protected]> <[email protected]>
*
* This file is provided under the following "BSD-style" License:
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef DART_COMMON_DETAIL_REQUIRESADDON_H_
#define DART_COMMON_DETAIL_REQUIRESADDON_H_

#include "dart/common/RequiresAddon.h"

namespace dart {
namespace common {

//==============================================================================
template <class ReqAddon>
RequiresAddon<ReqAddon>::RequiresAddon()
{
AddonManager::mRequiredAddons.insert(typeid(ReqAddon));
}

} // namespace common
} // namespace dart

#endif // DART_COMMON_DETAIL_REQUIRESADDON_H_
Loading