/** * PANDA 3D SOFTWARE * Copyright (c) Carnegie Mellon University. All rights reserved. * * All use of this software is subject to the terms of the revised BSD * license. You should have received a copy of this license along * with this source code in a file named "LICENSE." * * @file typeHandle.h * @author drose * @date 1998-10-23 */ #ifndef TYPEHANDLE_H #define TYPEHANDLE_H #include "dtoolbase.h" #include /** * The following illustrates the convention for declaring a type that uses * TypeHandle. In this example, ThisThingie inherits from TypedObject, which * automatically supplies some type-differentiation functions at the cost of * one virtual function, get_type(); however, this inheritance is optional, * and may be omitted to avoid the virtual function pointer overhead. (If you * do use TypedObject, be sure to consider whether your destructor should also * be virtual.) * * @code * class ThatThingie : public SimpleTypedObject { * public: * static TypeHandle get_class_type() { * return _type_handle; * } * static void init_type() { * register_type(_type_handle, "ThatThingie"); * } * * private: * static TypeHandle _type_handle; * }; * * class ThisThingie : public ThatThingie, publid TypedObject { * public: * static TypeHandle get_class_type() { * return _type_handle; * } * static void init_type() { * ThatThingie::init_type(); * TypedObject::init_type(); * register_type(_type_handle, "ThisThingie", * ThatThingie::get_class_type(), * TypedObject::get_class_type()); * } * virtual TypeHandle get_type() const { * return get_class_type(); * } * * private: * static TypeHandle _type_handle; * }; * @endcode */ class TypedObject; /** * TypeHandle is the identifier used to differentiate C++ class types. Any * C++ classes that inherit from some base class, and must be differentiated * at run time, should store a static TypeHandle object that can be queried * through a static member function named get_class_type(). Most of the time, * it is also desirable to inherit from TypedObject, which provides some * virtual functions to return the TypeHandle for a particular instance. * * At its essence, a TypeHandle is simply a unique identifier that is assigned * by the TypeRegistry. The TypeRegistry stores a tree of TypeHandles, so * that ancestry of a particular type may be queried, and the type name may be * retrieved for run-time display. */ class EXPCL_DTOOL_DTOOLBASE TypeHandle final { PUBLISHED: TypeHandle() noexcept = default; enum MemoryClass { MC_singleton, MC_array, MC_deleted_chain_active, MC_deleted_chain_inactive, MC_limit // Not a real value, just a placeholder for the maximum // enum value. }; // The default constructor must do nothing, because we can't guarantee // ordering of static initializers. If the constructor tried to initialize // its value, it might happen after the value had already been set // previously by another static initializer! PY_EXTENSION(static TypeHandle make(PyTypeObject *classobj)); INLINE bool operator == (const TypeHandle &other) const; INLINE bool operator != (const TypeHandle &other) const; INLINE bool operator < (const TypeHandle &other) const; INLINE bool operator <= (const TypeHandle &other) const; INLINE bool operator > (const TypeHandle &other) const; INLINE bool operator >= (const TypeHandle &other) const; INLINE int compare_to(const TypeHandle &other) const; INLINE size_t get_hash() const; INLINE std::string get_name(TypedObject *object = nullptr) const; INLINE bool is_derived_from(TypeHandle parent, TypedObject *object = nullptr) const; INLINE int get_num_parent_classes(TypedObject *object = nullptr) const; INLINE TypeHandle get_parent_class(int index) const; INLINE int get_num_child_classes(TypedObject *object = nullptr) const; INLINE TypeHandle get_child_class(int index) const; INLINE TypeHandle get_parent_towards(TypeHandle ancestor, TypedObject *object = nullptr) const; size_t get_memory_usage(MemoryClass memory_class) const; void inc_memory_usage(MemoryClass memory_class, size_t size); void dec_memory_usage(MemoryClass memory_class, size_t size); INLINE int get_index() const; INLINE void output(std::ostream &out) const; constexpr static TypeHandle none() { return TypeHandle(0); } INLINE operator bool () const; MAKE_PROPERTY(index, get_index); MAKE_PROPERTY(name, get_name); MAKE_SEQ_PROPERTY(parent_classes, get_num_parent_classes, get_parent_class); MAKE_SEQ_PROPERTY(child_classes, get_num_child_classes, get_child_class); PY_EXTENSION(PyObject *__reduce__() const); PY_EXTENSION(void __setstate__(PyObject *)); public: #ifdef HAVE_PYTHON PyTypeObject *get_python_type() const; PyObject *wrap_python(void *ptr, PyTypeObject *cast_from = nullptr) const; #endif // HAVE_PYTHON void *allocate_array(size_t size) RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT); void *reallocate_array(void *ptr, size_t size) RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT); void deallocate_array(void *ptr); constexpr static TypeHandle from_index(int index) { return TypeHandle(index); } private: constexpr TypeHandle(int index); int _index; friend class TypeRegistry; }; // It's handy to be able to output a TypeHandle directly, and see the type // name. INLINE std::ostream &operator << (std::ostream &out, TypeHandle type) { type.output(out); return out; } EXPCL_DTOOL_DTOOLBASE std::ostream &operator << (std::ostream &out, TypeHandle::MemoryClass mem_class); // We must include typeRegistry at this point so we can call it from our // inline functions. This is a circular include that is strategically placed // to do no harm. /* okcircular */ #include "typeRegistry.h" #include "typeHandle.I" #endif