dmlc--dgl
c2e61ce10b
* upd * simplify * further simplify * lint * doc * upd * upd * upd * upd * upd * upd * upd * lint * rename format * upd * lint * upd * upd * upd * udp * debug * upd * upd * upd * upd * upd * 无可厚非吧 * 中三边肥 * 你一定要喊吗 * lint * upd * upd * upd * upd * upd * upd * upd * Update unit_graph.h Co-authored-by: Zihao Ye <yzh119@192.168.0.110> Co-authored-by: Minjie Wang <wmjlyjemaine@gmail.com> Co-authored-by: Quan (Andy) Gan <coin2028@hotmail.com>
335 行
11 KiB
C++
335 行
11 KiB
C++
/*!
|
|
* Copyright (c) 2019 by Contributors
|
|
* \file runtime/object.h
|
|
* \brief Defines the Object data structures.
|
|
*/
|
|
#ifndef DGL_RUNTIME_OBJECT_H_
|
|
#define DGL_RUNTIME_OBJECT_H_
|
|
|
|
#include <dmlc/logging.h>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <memory>
|
|
#include <type_traits>
|
|
|
|
namespace dgl {
|
|
namespace runtime {
|
|
|
|
// forward declaration
|
|
class Object;
|
|
class ObjectRef;
|
|
class NDArray;
|
|
|
|
/*!
|
|
* \brief Visitor class to each object attribute.
|
|
* The content is going to be called for each field.
|
|
*/
|
|
class AttrVisitor {
|
|
public:
|
|
//! \cond Doxygen_Suppress
|
|
virtual void Visit(const char* key, double* value) = 0;
|
|
virtual void Visit(const char* key, int64_t* value) = 0;
|
|
virtual void Visit(const char* key, uint64_t* value) = 0;
|
|
virtual void Visit(const char* key, int* value) = 0;
|
|
virtual void Visit(const char* key, bool* value) = 0;
|
|
virtual void Visit(const char* key, std::string* value) = 0;
|
|
virtual void Visit(const char* key, ObjectRef* value) = 0;
|
|
virtual void Visit(const char* key, NDArray* value) = 0;
|
|
template<typename ENum,
|
|
typename = typename std::enable_if<std::is_enum<ENum>::value>::type>
|
|
void Visit(const char* key, ENum* ptr) {
|
|
static_assert(std::is_same<int, typename std::underlying_type<ENum>::type>::value,
|
|
"declare enum to be enum int to use visitor");
|
|
this->Visit(key, reinterpret_cast<int*>(ptr));
|
|
}
|
|
//! \endcond
|
|
};
|
|
|
|
/*!
|
|
* \brief base class of object container.
|
|
* All object's internal is stored as std::shared_ptr<Object>
|
|
*/
|
|
class Object {
|
|
public:
|
|
/*! \brief virtual destructor */
|
|
virtual ~Object() {}
|
|
/*! \return The unique type key of the object */
|
|
virtual const char* type_key() const = 0;
|
|
/*!
|
|
* \brief Apply visitor to each field of the Object
|
|
* Visitor could mutate the content of the object.
|
|
* override if Object contains attribute fields.
|
|
* \param visitor The visitor
|
|
*/
|
|
virtual void VisitAttrs(AttrVisitor* visitor) {}
|
|
/*! \return the type index of the object */
|
|
virtual uint32_t type_index() const = 0;
|
|
/*!
|
|
* \brief Whether this object derives from object with type_index=tid.
|
|
* Implemented by DGL_DECLARE_OBJECT_TYPE_INFO
|
|
*
|
|
* \param tid The type index.
|
|
* \return the check result.
|
|
*/
|
|
virtual bool _DerivedFrom(uint32_t tid) const;
|
|
/*!
|
|
* \brief get a runtime unique type index given a type key
|
|
* \param type_key Type key of a type.
|
|
* \return the corresponding type index.
|
|
*/
|
|
static uint32_t TypeKey2Index(const char* type_key);
|
|
/*!
|
|
* \brief get type key from type index.
|
|
* \param index The type index
|
|
* \return the corresponding type key.
|
|
*/
|
|
static const char* TypeIndex2Key(uint32_t index);
|
|
/*!
|
|
* \return whether the type is derived from
|
|
*/
|
|
template<typename T>
|
|
inline bool derived_from() const;
|
|
/*!
|
|
* \return whether the object is of type T
|
|
* \tparam The type to be checked.
|
|
*/
|
|
template<typename T>
|
|
inline bool is_type() const;
|
|
// object ref can see this
|
|
friend class ObjectRef;
|
|
static constexpr const char* _type_key = "Object";
|
|
};
|
|
|
|
|
|
/*! \brief base class of all reference object */
|
|
class ObjectRef {
|
|
public:
|
|
/*! \brief type indicate the container type */
|
|
using ContainerType = Object;
|
|
/*!
|
|
* \brief Comparator
|
|
*
|
|
* Compare with the two are referencing to the same object (compare by address).
|
|
*
|
|
* \param other Another object ref.
|
|
* \return the compare result.
|
|
* \sa same_as
|
|
*/
|
|
inline bool operator==(const ObjectRef& other) const;
|
|
/*!
|
|
* \brief Comparator
|
|
*
|
|
* Compare with the two are referencing to the same object (compare by address).
|
|
*
|
|
* \param other Another object ref.
|
|
* \return the compare result.
|
|
*/
|
|
inline bool same_as(const ObjectRef& other) const;
|
|
/*!
|
|
* \brief Comparator
|
|
*
|
|
* The operator overload allows ObjectRef be used in std::map.
|
|
*
|
|
* \param other Another object ref.
|
|
* \return the compare result.
|
|
*/
|
|
inline bool operator<(const ObjectRef& other) const;
|
|
/*!
|
|
* \brief Comparator
|
|
* \param other Another object ref.
|
|
* \return the compare result.
|
|
* \sa same_as
|
|
*/
|
|
inline bool operator!=(const ObjectRef& other) const;
|
|
/*! \return the hash function for ObjectRef */
|
|
inline size_t hash() const;
|
|
/*! \return whether the expression is null */
|
|
inline bool defined() const;
|
|
/*! \return the internal type index of Object */
|
|
inline uint32_t type_index() const;
|
|
/*! \return the internal object pointer */
|
|
inline const Object* get() const;
|
|
/*! \return the internal object pointer */
|
|
inline const Object* operator->() const;
|
|
/*!
|
|
* \brief Downcast this object to its actual type.
|
|
* This returns nullptr if the object is not of the requested type.
|
|
* Example usage:
|
|
*
|
|
* if (const Banana *banana = obj->as<Banana>()) {
|
|
* // This is a Banana!
|
|
* }
|
|
* \tparam T the target type, must be subtype of Object
|
|
*/
|
|
template<typename T>
|
|
inline const T *as() const;
|
|
|
|
/*! \brief default constructor */
|
|
ObjectRef() = default;
|
|
explicit ObjectRef(std::shared_ptr<Object> obj) : obj_(obj) {}
|
|
|
|
/*! \brief the internal object, do not touch */
|
|
std::shared_ptr<Object> obj_;
|
|
};
|
|
|
|
/*!
|
|
* \brief helper macro to declare type information in a base object.
|
|
*
|
|
* This is macro should be used in abstract base class definition
|
|
* because it does not define type_key and type_index.
|
|
*/
|
|
#define DGL_DECLARE_BASE_OBJECT_INFO(TypeName, Parent) \
|
|
const bool _DerivedFrom(uint32_t tid) const override { \
|
|
static uint32_t tidx = TypeKey2Index(TypeName::_type_key); \
|
|
if (tidx == tid) return true; \
|
|
return Parent::_DerivedFrom(tid); \
|
|
}
|
|
|
|
/*!
|
|
* \brief helper macro to declare type information in a terminal class
|
|
*
|
|
* This is macro should be used in terminal class definition.
|
|
*
|
|
* For example:
|
|
*
|
|
* // This class is an abstract class and cannot create instances
|
|
* class SomeBaseClass : public Object {
|
|
* public:
|
|
* static constexpr const char* _type_key = "some_base";
|
|
* DGL_DECLARE_BASE_OBJECT_INFO(SomeBaseClass, Object);
|
|
* };
|
|
*
|
|
* // Child class that allows instantiation
|
|
* class SomeChildClass : public SomeBaseClass {
|
|
* public:
|
|
* static constexpr const char* _type_key = "some_child";
|
|
* DGL_DECLARE_OBJECT_TYPE_INFO(SomeChildClass, SomeBaseClass);
|
|
* };
|
|
*/
|
|
#define DGL_DECLARE_OBJECT_TYPE_INFO(TypeName, Parent) \
|
|
const char* type_key() const final { \
|
|
return TypeName::_type_key; \
|
|
} \
|
|
uint32_t type_index() const final { \
|
|
static uint32_t tidx = TypeKey2Index(TypeName::_type_key); \
|
|
return tidx; \
|
|
} \
|
|
bool _DerivedFrom(uint32_t tid) const final { \
|
|
static uint32_t tidx = TypeKey2Index(TypeName::_type_key); \
|
|
if (tidx == tid) return true; \
|
|
return Parent::_DerivedFrom(tid); \
|
|
}
|
|
|
|
/*! \brief Macro to generate common object reference class method definition */
|
|
#define DGL_DEFINE_OBJECT_REF_METHODS(TypeName, BaseTypeName, ObjectName) \
|
|
TypeName() {} \
|
|
explicit TypeName(std::shared_ptr<runtime::Object> obj): BaseTypeName(obj) {} \
|
|
const ObjectName* operator->() const { \
|
|
return static_cast<const ObjectName*>(obj_.get()); \
|
|
} \
|
|
ObjectName* operator->() { \
|
|
return static_cast<ObjectName*>(obj_.get()); \
|
|
} \
|
|
std::shared_ptr<ObjectName> sptr() const { \
|
|
return CHECK_NOTNULL(std::dynamic_pointer_cast<ObjectName>(obj_)); \
|
|
} \
|
|
operator bool() const { return this->defined(); } \
|
|
using ContainerType = ObjectName
|
|
|
|
/*! \brief Macro to generate object reference class definition */
|
|
#define DGL_DEFINE_OBJECT_REF(TypeName, ObjectName) \
|
|
class TypeName : public ::dgl::runtime::ObjectRef { \
|
|
public: \
|
|
DGL_DEFINE_OBJECT_REF_METHODS(TypeName, ::dgl::runtime::ObjectRef, ObjectName); \
|
|
}
|
|
|
|
// implementations of inline functions after this
|
|
template<typename T>
|
|
inline bool Object::is_type() const {
|
|
// use static field so query only happens once.
|
|
static uint32_t type_id = Object::TypeKey2Index(T::_type_key);
|
|
return type_id == this->type_index();
|
|
}
|
|
|
|
template<typename T>
|
|
inline bool Object::derived_from() const {
|
|
// use static field so query only happens once.
|
|
static uint32_t type_id = Object::TypeKey2Index(T::_type_key);
|
|
return this->_DerivedFrom(type_id);
|
|
}
|
|
|
|
inline const Object* ObjectRef::get() const {
|
|
return obj_.get();
|
|
}
|
|
|
|
inline const Object* ObjectRef::operator->() const {
|
|
return obj_.get();
|
|
}
|
|
|
|
inline bool ObjectRef::defined() const {
|
|
return obj_.get() != nullptr;
|
|
}
|
|
|
|
inline bool ObjectRef::operator==(const ObjectRef& other) const {
|
|
return obj_.get() == other.obj_.get();
|
|
}
|
|
|
|
inline bool ObjectRef::same_as(const ObjectRef& other) const {
|
|
return obj_.get() == other.obj_.get();
|
|
}
|
|
|
|
inline bool ObjectRef::operator<(const ObjectRef& other) const {
|
|
return obj_.get() < other.obj_.get();
|
|
}
|
|
|
|
inline bool ObjectRef::operator!=(const ObjectRef& other) const {
|
|
return obj_.get() != other.obj_.get();
|
|
}
|
|
|
|
inline size_t ObjectRef::hash() const {
|
|
return std::hash<Object*>()(obj_.get());
|
|
}
|
|
|
|
inline uint32_t ObjectRef::type_index() const {
|
|
CHECK(obj_.get() != nullptr) << "null type";
|
|
return get()->type_index();
|
|
}
|
|
|
|
template<typename T>
|
|
inline const T* ObjectRef::as() const {
|
|
const Object* ptr = get();
|
|
if (ptr && ptr->is_type<T>()) {
|
|
return static_cast<const T*>(ptr);
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
/*! \brief The hash function for nodes */
|
|
struct ObjectHash {
|
|
size_t operator()(const ObjectRef& a) const {
|
|
return a.hash();
|
|
}
|
|
};
|
|
|
|
/*! \brief The equal comparator for nodes */
|
|
struct ObjectEqual {
|
|
bool operator()(const ObjectRef& a, const ObjectRef& b) const {
|
|
return a.get() == b.get();
|
|
}
|
|
};
|
|
|
|
} // namespace runtime
|
|
} // namespace dgl
|
|
|
|
namespace std {
|
|
template <>
|
|
struct hash<::dgl::runtime::ObjectRef> {
|
|
std::size_t operator()(const ::dgl::runtime::ObjectRef& k) const {
|
|
return k.hash();
|
|
}
|
|
};
|
|
|
|
} // namespace std
|
|
|
|
#endif // DGL_RUNTIME_OBJECT_H_
|