diff --git a/Control/SGTools/SGTools/BaseInfo.h b/Control/SGTools/SGTools/BaseInfo.h new file mode 100755 index 0000000000000000000000000000000000000000..74868f25ace2519dea70fac606bad536f601e3ee --- /dev/null +++ b/Control/SGTools/SGTools/BaseInfo.h @@ -0,0 +1,902 @@ +// This file's extension implies that it's C, but it's really -*- C++ -*-. + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// $Id: BaseInfo.h,v 1.11 2008-12-15 16:22:45 ssnyder Exp $ + +/** + * @file SGTools/BaseInfo.h + * @author scott snyder + * @date Nov 2005 + * @brief Provide an interface for finding inheritance information + * at run time. + * + * The @a SG::BaseInfo<T> class provides an interface for finding + * inheritance information about class @a T. In the absence of compiler + * support for reflection, the inheritance information must be + * explicitly declared. This is done with the @a SG_BASE macro + * and friends. To declare that class @a D derives from class @a B, use + * + *@code + * struct B {}; + * struct D : public B {}; + * SG_BASE (D, B); + @endcode + * + * You can also use multiple inheritance with the @a SG_BASES2 + * and @a SG_BASES3 macros: + * + *@code + * struct B1 {}; + * struct B2 {}; + * struct B3 {}; + * struct D : public B1, public B2, public B3 {}; + * SG_BASES3 (D, B1, B2, B3); + @endcode + * + * Supporting more than three base classes requires (straightforward) + * changes to the code here. + * + * If any of the derivations are virtual, the corresponding + * base class should be within a @a SG_VIRTUAL macro: + * + *@code + * struct B1 {}; + * struct B2 {}; + * struct D : public B1, virtual public B2 {}; + * SG_BASES2 (D, B1, SG_VIRTUAL (B2)); + @endcode + * + * Note that these macros will only work with non-templated types, + * or with specific instantiations of templated types. If you want + * a templated @a SG_BASE, you'll need to declare the specialization + * yourself. You should specialize @a SG::Bases<T>, defining types + * @a Base1, @a Base2, and @a Base3 (which should be @a SG::NoBase + * if not used). Example: + * + *@code + * template <class T> struct B {}; + * template <class T> struct D : public B<T> {}; + * namespace SG { + * template <class T> + * struct Bases<D<T> > { + * typedef B<T> Base1; + * typedef NoBase Base2; + * typedef NoBase Base3; + * }; + * } + @endcode + * + * Once these declarations are in place, what can you do with it? + * The interface is provided by the @a SG::BaseInfo<T> class. + * (This is a wrapper around a singleton, so it's not expensive + * to create instances of this class.) You can specify the base + * classes either by the Gaudi class ID or by the C++ @c std::type_info. + * Of course, you'll only be able to get information by class ID + * if the classes actually have IDs defined. + * + * Here are the available methods of @a SG::BaseInfo<T>: + * + *@code + * static bool is_base (CLID clid) + * static bool is_base (const std::type_info& tinfo) + @endcode + * Test to see if the type given by @a clid or @a tinfo + * is a base of @a T. Note that @a T counts as its own base. + * + *@code + * static bool is_virtual (CLID clid) + * static bool is_virtual (const std::type_info& tinfo) + @endcode + * Test to see if the type given by @a clid or @a tinfo + * is a virtual base of @a T. This should always be @a false + * for @a T itself. + * + *@code + * static void* cast (T* p, CLID clid) + * static void* cast (T* p, const std::type_info& tinfo) + @endcode + * Cast a pointer from @a T* to a pointer to the type given + * by @a clid or @a tinfo, which must be a base if @a T + * known to @a BaseInfo. The result is returned as a @a void*. + * If the conversion cannot be done (because the target is not + * known to be a base of @a T), then 0 is returned. + * + *@code + * static T* castTo (void* p, CLID clid) + * static T* castTo (void* p, const std::type_info& tinfo) + @endcode + * Similar, except converts from a pointer to the type given by + * @a clid or @a tinfo (which must be a base of @a T) to @a T*. + * This involves a @a dynamic_cast. Returns 0 if the cast fails. + * + *@code + * static std::vector<CLID> get_bases () + @endcode + * Return all the known bases of @a T (that have class IDs). + * @a T itself will be included in this list. + * + *@code + * static std::vector<const std::type_info*> get_ti_bases () + @endcode + * Return all the known bases of @a T. + * @a T itself will be included in this list. + * + * It is also possible to get a non-templated version of @c SG::BaseInfo<T>. + * This is called @c SG::BaseInfoBase. These objects can be found using + * @c SG::BaseInfoBase::find, by either class ID or @c std::type_info + * (in order for this to work, the corresponding @c SG::BaseInfo<T> class + * must have been used somewhere in the program). The interface + * of @c SG::BaseInfoBase is the same as @c SG::BaseInfo<T>, except + * that @c void* replaces @c T* in the @c cast methods. + * + * Initialization issues: We don't want to build the @c SG::BaseInfo<T> + * objects at static initialization time. But we do need to remember + * which ones are available. Thus, @c BaseInfoBase maintains a list + * of CLIDs and @c std::type_info's for which we may not have done + * initialization, along with a function to call to do the initialization. + * The initialization list is filled during static initialization. + * When we look for an instance, if we don't find one, we look in the + * initialization list; if there's a match there, we run the initialization + * and remove it from the list. + * + * Copy conversions: The conversion machinery above provides access to the + * standard C++ base<>derived conversions. However, sometimes you'd like + * to allow additional conversions as well, for example between a + * vector<ElementLink<T> > and DataVector<T>. For those cases, + * you can register a conversion function with the _source_ type + * that can initialize an instance of the _destination_ type + * from the _source_ type. Then, when you try to retrieve the object + * from StoreGate with the _destination_ type, your conversion function + * will be called. + * + * Your conversion function should be the method @a convert of + * a class deriving from the @a SG::CopyConversion template; + * for example, + * + *@code + * class MyCopyConversion + * : public SG::CopyConversion<std::vector<ElementLink<MyType> >, + * DataVector<MyType> > + * { + * public: + * virtual void convert (const std::vector<ElementLink<MyType> >& src, + * DataVector<MyType>& dst) const + * { + * size_t sz = src.size(); + * if (dst.size() != sz) { + * dst.clear (SG::VIEW_ELEMENTS); + * dst.reserve (sz); + * for (size_t i = 0; i < sz; i++) { + * const MyType* p = *(src[i]).cptr(); + * dst.push_back (const_cast<MyType*> (p)); + * } + * } + * } + * }; + @endcode + * + * You then declare this using the macro + * + @code + * SG_ADD_COPY_CONVERSION (std::vector<ElementLink<MyType> >, + * MyCopyConversion); + @endcode + * + * Copy conversions are enabled only for objects that have been marked as const. + */ + +#ifndef SGTOOLS_BASEINFO_H +#define SGTOOLS_BASEINFO_H + +#include "GaudiKernel/ClassID.h" +#include <vector> +#include <typeinfo> + + +//=========================================================================== +// Macros used to declare base class information. +// + +/** + * @brief Used to mark virtual derivation. + * When using the @a SG_BASE macros below, use this in the case + * of virtual derivation. Example: + * + *@code + * struct B1 {}; + * struct B2 {}; + * struct D : public B1, virtual public B2 {}; + * SG_BASES2 (D, B1, SG_VIRTUAL (B2)); + @endcode + */ +#define SG_VIRTUAL(T) Virtual<T> + + +/** + * @brief Declare that class @a D derives from class @a B. Example: + * + *@code + * struct B {}; + * struct D : public B {}; + * SG_BASE (D, B); + @endcode + */ +#define SG_BASE(D, B) SG_BASES1(D, B) + + +/** + * @brief Declare that class @a D derives from class @a B. + * This is the same as @a SG_BASE. Example: + * + *@code + * struct B {}; + * struct D : public B {}; + * SG_BASES1 (D, B); + @endcode + */ +#define SG_BASES1(D, B) \ + namespace SG { \ + template<> struct Bases<D >{ \ + typedef B Base1; \ + typedef NoBase Base2; \ + typedef NoBase Base3; \ + }; \ + template struct BaseInit<D >; \ +} struct sg_dummy // to swallow semicolon + + +/** + * @brief Declare that class @a D derives from classes @a B1 and @a B2. + * Example: + * + *@code + * struct B1 {}; + * struct B2 {}; + * struct D : public B1, public B2 {}; + * SG_BASES2 (D, B1, B2); + @endcode + */ +#define SG_BASES2(D, B1, B2) \ + namespace SG { \ + template<> struct Bases<D >{ \ + typedef B1 Base1; \ + typedef B2 Base2; \ + typedef NoBase Base3; \ + }; \ + template struct BaseInit<D >; \ +} struct sg_dummy // to swallow semicolon + + +/** + * @brief Declare that class @a D derives from classes @a B1, @a B2, and @a B3. + * Example: + * + *@code + * struct B1 {}; + * struct B2 {}; + * struct B3 {}; + * struct D : public B1, public B2, public B3 {}; + * SG_BASES3 (D, B1, B2, B3); + @endcode + */ +#define SG_BASES3(D, B1, B2, B3) \ + namespace SG { \ + template<> struct Bases<D >{ \ + typedef B1 Base1; \ + typedef B2 Base2; \ + typedef B3 Base3; \ + }; \ + template struct BaseInit<D >; \ +} struct sg_dummy // to swallow semicolon + + + +/** + * @brief Add a new base class @c B to class @c D. + * + * Sometimes, the SG_BASE macro for a class isn't present in its header. + * + * One can try to put the appropriate SG_BASE macro somewhere else, + * but this doesn't always work: if the @c BaseInfoBase for @c D has + * already been created by the time the @c SG_BASE initialization + * runs, then that @c SG_BASE macro won't do anything. + * + * @c SG_ADD_BASE, however, will add a new base to an existing @c BaseInfoBase. + * + *@code + * struct B {}; + * struct D : public B {}; + * SG_ADD_BASES (D, B); + @endcode + */ +#define SG_ADD_BASE(D, B) \ + namespace SG { \ + template struct AddBaseInit<D, B >; \ +} struct sg_dummy // to swallow semicolon + + +/** + * @brief Declare a copy conversion from class @c T using converter @c C. + * + * See the comments in the header for a detailed description. + */ +#define SG_ADD_COPY_CONVERSION(D, C) \ + namespace SG { \ + template struct AddCopyConversionInit<D, C >; \ +} struct sg_dummy // to swallow semicolon + + + +namespace SG { + + +/** + * @brief Helper metafunction to get base class types. + * + * For a class @c T, + *@code + * SG::BaseType<SG::Bases<T>::Base1>::type + @endcode + * gives the type of @c T's first base. Also, + *@code + * SG::BaseType<SG::Bases<T>::Base1>::is_virtual + @endcode + * tells whether the derivation is virtual + * (either @c true_type or @c false_type). + * + * Note that @c SG::Bases\<T>::Base1 is not the actual type + * of @c T's first base if virtual derivation was used. + */ +template <class T> +struct BaseType; + + +// Forward declaration. +template <class T> +class BaseInfoImpl; + + +struct BaseInfoBaseImpl; + + +//=========================================================================== +// Copy conversion declarations. +// + + +/** + * @brief Base class for copy conversions. + */ +class CopyConversionBase +{ +public: + /// Destructor. + virtual ~CopyConversionBase() {} + + /// Create an instance of the destination class. + virtual void* create() const = 0; + + /// Destroy an instance of the destination class. + virtual void destroy (void* p) const = 0; + + /// Convert the contents of an instance of the source class SRC + /// to an instance of the destination class DST. + virtual void convertUntyped (const void* src, void* dst) const = 0; +}; + + +/** + * @brief Base class for copy conversions, templated on source + * and destination classes. + */ +template <class SRC, class DST> +class CopyConversion + : public CopyConversionBase +{ +public: + /// The destination class. + typedef DST target_type; + + /// Create an instance of the destination class. + virtual void* create() const { return new DST; } + + /// Destroy an instance of the destination class. + virtual void destroy (void* p) const { delete reinterpret_cast<DST*>(p); } + + /// Convert the contents of an instance of the source class SRC + /// to an instance of the destination class DST. + virtual void convertUntyped (const void* src, void* dst) const + { + convert (*reinterpret_cast<const SRC*>(src), + *reinterpret_cast<DST*>(dst)); + } + + /// Convert the contents of an instance of the source class SRC + /// to an instance of the destination class DST. + /// (Type-safe version.) + virtual void convert (const SRC& src, DST& dst) const = 0; +}; + + +//=========================================================================== +// Base class declaration. +// This factors out the part of the implementation that doesn't +// depend on the template parameter @a T. +// + + +/** + * @brief The non-template portion of the @a BaseInfo implementation. + */ +class BaseInfoBase +{ +public: + /** + * @brief Return the CLID for this class. + */ + CLID clid() const; + + + /** + * @brief Return the @c std::type_info for this class. + */ + const std::type_info& typeinfo() const; + + + /** + * @brief Cast to a base pointer. + * @param p The pointer to cast (a @a T* cast to a @a void*). + * @param clid ID of the class to which to cast. + * @return The pointer cast to the requested type, returned + * as a @a void*. @a clid must be known to be a base + * of @a T; otherwise, 0 will be returned. + */ + void* cast (void* p, CLID clid) const; + + /** + * @brief Cast to a base pointer. + * @param p The pointer to cast (a @a T* cast to a @a void*). + * @param clid @a type_info of the class to which to cast. + * @return The pointer cast to the requested type, returned + * as a @a void*. @a tinfo must be known to be a base + * of @a T; otherwise, 0 will be returned. + */ + void* cast (void* p, const std::type_info& tinfo) const; + + + /** + * @brief Cast to a derived pointer. + * @param p The pointer to cast (a @a B* cast to a @a void*). + * @param clid ID of the class @a B from which to cast. + * @return The pointer cast to the requested type, returned + * as a @a void*. @a clid must be known to be a base + * of @a T; otherwise, 0 will be returned. + * 0 will also be returned if the @a dynamic_cast fails. + */ + void* castTo (void* p, CLID clid) const; + + /** + * @brief Cast to a derived pointer. + * @param p The pointer to cast (a @a B* cast to a @a void*). + * @param clid @a type_info of the class @a B from which to cast. + * @return The pointer cast to the requested type, returned + * as a @a void*. @a tinfo must be known to be a base + * of @a T; otherwise, 0 will be returned. + * 0 will also be returned if the @a dynamic_cast fails. + */ + void* castTo (void* p, const std::type_info& tinfo) const; + + + /// Type of a pointer conversion function. + typedef void* castfn_t (void* p); + + + // gcc 4.3 complains about the code genreflex generates for these. + // They're not useful from python anyway, so just suppress them. +#ifndef __REFLEX__ + /** + * @brief Return a function for casting to a base pointer. + * @param clid ID of the class to which to cast. + * @return A function to convert a pointer to a @c T to a pointer + * to the type identified by @a clid. + * @a clid must be known to be a base + * of @a T; otherwise, 0 will be returned. + */ + castfn_t* castfn (CLID clid) const; + + + /** + * @brief Return a function for casting to a base pointer. + * @param clid @a type_info of the class to which to cast. + * @return A function to convert a pointer to a @c T to a pointer + * to the type identified by @a tinfo. + * @a tinfo must be known to be a base + * of @a T; otherwise, 0 will be returned. + */ + castfn_t* castfn (const std::type_info& tinfo) const; + + /** + * @brief Return a function for casting to a derived pointer. + * @param clid ID of the class @a B from which to cast. + * @return A function to convert a pointer to a @a B to a pointer + * to a @a T. @a B must be known to be a base + * of @a T; otherwise, 0 will be returned. + * 0 will also be returned if the @a dynamic_cast fails. + */ + castfn_t* castfnTo (CLID clid) const; + + + /** + * @brief Return a function for casting to a derived pointer. + * @param clid @a type_info of the class @a B from which to cast. + * @return A function to convert a pointer to a @a B to a pointer + * to a @a T. @a B must be known to be a base + * of @a T; otherwise, 0 will be returned. + * 0 will also be returned if the @a dynamic_cast fails. + */ + castfn_t* castfnTo (const std::type_info& tinfo) const; +#endif + + + /** + * @brief Return the class IDs of all known bases of @a T (that + * have class IDs). The list will include @a T itself. + */ + std::vector<CLID> get_bases () const; + + /** + * @brief Return the @c type_info's of all known bases of @a T. + * The list will include @a T itself. + */ + std::vector<const std::type_info*> get_ti_bases () const; + + /** + * @brief Return true if @a clid is the ID of a class that + * is known to be a base of @a T. @a T is considered + * to be its own base for this purpose. + * @param clid The ID of the class to test. + */ + bool is_base (CLID clid) const; + + /** + * @brief Return true if @a tinfo is the @a type_info of a class that + * is known to be a base of @a T. @a T is considered + * to be its own base for this purpose. + * @param clid The ID of the class to test. + */ + bool is_base (const std::type_info& tinfo) const; + + + /** + * @brief Return true if @a clid is the ID of a class that + * is known to be a virtual base of @a T. (This will always + * be false for @a T itself.) + * @param clid The ID of the class to test. + */ + bool is_virtual (CLID clid) const; + + /** + * @brief Return true if @a tinfo is the @a std::type_info of a class that + * is known to be a virtual base of @a T. (This will always + * be false for @a T itself.) + * @param tinfo The @a std::type_info of the class to test. + */ + bool is_virtual (const std::type_info& tinfo) const; + + + /** + * @brief Search for a copy conversion to @c tinfo. + * @param tinfo The class to which we want to convert. + * + * Returns the conversion instance or 0. + */ + const CopyConversionBase* copy_conversion (const std::type_info& tinfo) const; + + + /** + * @brief Search for a copy conversion to @c clid. + * @param clid The class to which we want to convert. + * + * Returns the conversion instance or 0. + */ + const CopyConversionBase* copy_conversion (CLID clid) const; + + + /** + * @brief Add a new copy conversion. + * @param clid The @c CLID of the target class. + * @param tinfo The @c std::type_info of the target class. + * @param cnv A @c CopyConversionBase instance describing the conversion. + * + * The @c BaseInfoBase takes ownership of the @c cnv object. + */ + void add_copy_conversion (CLID clid, + const std::type_info& tinfo, + const CopyConversionBase* cnv); + + + /** + * @brief Return known copy conversions. + * + * Returns the CLIDs of all target classes that have been registered + * with this one for copy conversion. + */ + std::vector<CLID> get_copy_conversions() const; + + +#ifndef __REFLEX__ + /** + * @brief Add information about one base class. + * @param clid The class ID of the base. May be @a CLID_NULL if no + * class ID is available. + * @param tinfo The @a std::type_info of the base. + * @param converter Converter function. This should be able to + * convert a @a T* to a pointer to this base. + * @param converterTo Converter function. This should be able to + * convert a pointer to this base to a @a T*. + * @param is_virtual True if the derivation from this base to @a T + * is via virtual derivation. + */ + void add_info (CLID clid, + const std::type_info& tinfo, + castfn_t* converter, + castfn_t* converterTo, + bool is_virtual); +#endif + + + /** + * @brief Find the @c BaseInfoBase instance for @c clid. + * @param clid The class ID of the class for which we want information. + * + * Returns 0 if no @c BaseInfoBase instance is available. + */ + static const BaseInfoBase* find (CLID clid); + + + /** + * @brief Find the @c BaseInfoBase instance for @c tinfo. + * @param tinfo The @c std::type_info of the class + * for which we want information. + * + * Returns 0 if no @c BaseInfoBase instance is available. + */ + static const BaseInfoBase* find (const std::type_info& tinfo); + + + /// Type for an initialization function. + typedef const BaseInfoBase& init_func_t(); + + +#ifndef __REFLEX__ + /** + * @brief Register an initialization function. + * @param clid The class ID of the class being registered. + * @param tinfo The @c std::type_info for the class being registered. + * @param init_func Function to initialize @c BaseInfo for the class. + */ + static void addInit (CLID clid, + const std::type_info* tinfo, + init_func_t* init_func); +#endif + + + /** + * @brief Run initializations for this class, if needed. + */ + void maybeInit(); + + +protected: + /** + * @brief Constructor. + * @param clid The class ID of this class. May be @c CLID_NULL if no + * ID is available. + * @param tinfo The @c std::type_info for this class. + */ + BaseInfoBase (CLID clid, const std::type_info& tinfo); + + + /** + * @brief Destructor. + */ + ~BaseInfoBase(); + + +private: + /** + * @brief Try to translate a type_info to a CLID by looking in the initlist. + * @param tinfo The type to translate. + * @returns The corresponding CLID, or CLID_NULL. + */ + CLID clid_from_initlist (const std::type_info& tinfo); + + + /// Pointer to internal state. + BaseInfoBaseImpl* m_impl; + + BaseInfoBase (const BaseInfoBase&); + BaseInfoBase& operator= (const BaseInfoBase&); +}; + + +//=========================================================================== +// The templated @c BaseInfo class. +// + +/** + * @brief Provide an interface for finding inheritance information + * at run time. See the file comments for full details. + */ +template <class T> +class BaseInfo +{ +public: + /** + * @brief Cast to a base pointer. + * @param p The pointer to cast. + * @param clid ID of the class to which to cast. + * @return The pointer cast to the requested type, returned + * as a @a void*. @a clid must be known to be a base + * of @a T; otherwise, 0 will be returned. + */ + static void* cast (T* p, CLID clid); + + /** + * @brief Cast to a base pointer. + * @param p The pointer to cast. + * @param clid @a type_info of the class to which to cast. + * @return The pointer cast to the requested type, returned + * as a @a void*. @a tinfo must be known to be a base + * of @a T; otherwise, 0 will be returned. + */ + static void* cast (T* p, const std::type_info& tinfo); + + + /** + * @brief Cast to a derived pointer. + * @param p The pointer to cast. + * @param clid ID of the class @a B from which to cast. + * @return The pointer cast to a @a T*. + * @a B must be known to be a base + * of @a T; otherwise, 0 will be returned. + * 0 will also be returned if the @a dynamic_cast fails. + */ + static T* castTo (void* p, CLID clid); + + /** + * @brief Cast to a derived pointer. + * @param p The pointer to cast. + * @param clid @a type_info of the class @a B from which to cast. + * @return The pointer cast to a @a T*. + * @a B must be known to be a base + * of @a T; otherwise, 0 will be returned. + * 0 will also be returned if the @a dynamic_cast fails. + */ + static T* castTo (void* p, const std::type_info& tinfo); + + + /** + * @brief Return a function for casting to a base pointer. + * @param clid ID of the class to which to cast. + * @return A function to convert a pointer to a @c T to a pointer + * to the type identified by @a clid. + * @a clid must be known to be a base + * of @a T; otherwise, 0 will be returned. + */ + static BaseInfoBase::castfn_t* castfn (CLID clid); + + + /** + * @brief Return a function for casting to a base pointer. + * @param clid @a type_info of the class to which to cast. + * @return A function to convert a pointer to a @c T to a pointer + * to the type identified by @a tinfo. + * @a tinfo must be known to be a base + * of @a T; otherwise, 0 will be returned. + */ + static BaseInfoBase::castfn_t* castfn (const std::type_info& tinfo); + + + /** + * @brief Return a function for casting to a derived pointer. + * @param clid ID of the class @a B from which to cast. + * @return A function to convert a pointer to a @c T to a pointer + * to a @a T. @a clid must be known to be a base + * of @a T; otherwise, 0 will be returned. + * 0 will also be returned if the @a dynamic_cast fails. + */ + static BaseInfoBase::castfn_t* castfnTo (CLID clid); + + + /** + * @brief Return a function for casting to a derived pointer. + * @param clid @a type_info of the class @a B from which to cast. + * @return A function to convert a pointer to a @c B to a pointer + * to a @T. @a tinfo must be known to be a base + * of @a T; otherwise, 0 will be returned. + * 0 will also be returned if the @a dynamic_cast fails. + */ + static BaseInfoBase::castfn_t* castfnTo (const std::type_info& tinfo); + + + /** + * @brief Return the class IDs of all known bases of @a T (that + * have class IDs). The list will include @a T itself. + */ + static std::vector<CLID> get_bases (); + + + /** + * @brief Return the @c type_info's of all known bases of @a T. + * The list will include @a T itself. + */ + static std::vector<const std::type_info*> get_ti_bases (); + + + /** + * @brief Return true if @a clid is the ID of a class that + * is known to be a base of @a T. @a T is considered + * to be its own base for this purpose. + * @param clid The ID of the class to test. + */ + static bool is_base (CLID clid); + + /** + * @brief Return true if @a tinfo is the @a std::type_info of a class that + * is known to be a base of @a T. @a T is considered + * to be its own base for this purpose. + * @param tinfo The @a std::type_info of the class to test. + */ + static bool is_base (const std::type_info& tinfo); + + + /** + * @brief Return true if @a clid is the ID of a class that + * is known to be a virtual base of @a T. (This will always + * be false for @a T itself.) + * @param clid The ID of the class to test. + */ + static bool is_virtual (CLID clid); + + /** + * @brief Return true if @a tinfo is the @a std::type_info of a class that + * is known to be a virtual base of @a T. (This will always + * be false for @a T itself.) + * @param tinfo The @a std::type_info of the class to test. + */ + static bool is_virtual (const std::type_info& tinfo); + + + /** + * @brief Return the non-templated @c BaseInfoBase object for this type. + */ + static const BaseInfoBase& baseinfo (); + + +private: + /// Return a reference to the (singleton) implementation object + /// for this class. + static const BaseInfoImpl<T>& instance(); + + /// This holds the singleton implementation object instance. + struct instance_holder + { + instance_holder(); + BaseInfoImpl<T>* instance; + }; + static instance_holder s_instance; +}; + + +} // namespace SG + + +#include "SGTools/BaseInfo.icc" + + +#endif // not SGTOOLS_BASEINFO_H + diff --git a/Control/SGTools/SGTools/BaseInfo.icc b/Control/SGTools/SGTools/BaseInfo.icc new file mode 100755 index 0000000000000000000000000000000000000000..9524cca44423fb2fc00232690b16a1ee8fae3491 --- /dev/null +++ b/Control/SGTools/SGTools/BaseInfo.icc @@ -0,0 +1,654 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// $Id: BaseInfo.icc,v 1.9 2008-12-15 15:12:39 ssnyder Exp $ +/** + * @file SGTools/BaseInfo.icc + * @author scott snyder + * @date Nov 2005 + * @brief Provide an interface for finding inheritance information + * at run time. + * Implementation file. + */ + + +#include "SGTools/safe_clid.h" +#include "boost/type_traits/is_polymorphic.hpp" + + +namespace SG { + + +//=========================================================================== +// Inheritance data representation classes. +// + + +/** + * @brief Marker to indicate a nonexistent base class. + */ +struct NoBase {}; + + +/** + * @brief Wrapper to indicate virtual derivation. + * @a Virtual<T> will mean that derivation from @a T is virtual. + */ +template <class T> struct Virtual {}; + + +/** + * @brief Traits class to hold derivation information for up to three + * base classes. + * + * @a Base1, etc., get typedef'd to the appropriate + * base classes. Use @a NoBase if there is no base class; use + * @a Virtual<T> to indicate virtual derivation. This class should + * be specialized for every class @a T for which we want to know + * inheritance information. + */ +template <class T> +struct Bases +{ + typedef NoBase Base1; + typedef NoBase Base2; + typedef NoBase Base3; +}; + + +// Helper metafunction to get base class types. +// Generic case. +template <class T> +struct BaseType +{ + typedef T type; + typedef boost::false_type is_virtual; +}; + + +// Helper metafunction to get base class types. +// Virtual derivation case. +template <class T> +struct BaseType<Virtual<T> > +{ + typedef T type; + typedef boost::true_type is_virtual; +}; + + +//=========================================================================== +// Internal implementation class for @a BaseInfo. +// This is used as a singleton, and should be accessed using the @a BaseInfo +// wrapper class. +// + +/** + * @brief Internal implementation class for @a BaseInfo. + */ +template <class T> +class BaseInfoImpl + : public BaseInfoBase +{ +public: + /** + * @brief Constructor. + */ + BaseInfoImpl(); + + + /** + * @brief Add information about base class @a B (for @a T). + * @param is_virtual True if the derivation from @a B to @a T + * is via virtual derivation. + */ +#ifdef __REFLEX__ + template <class B> + void add_base (bool is_virtual); +#else + template <class B> + void add_base (bool is_virtual) + { + // Add the information for this base. + // Note the use of @a safe_clid to allow this to work whether or not + // there is actually a class ID defined for @a B. + // We pass in the converter function and the virtual flag. + this->add_info (SG::safe_clid<B>(), typeid(B), + converter<B>, converterTo<B>, is_virtual); + } +#endif + +private: + /** + * @brief Converter function. + * @param p Pointer to convert. A @a T* converted to a @a void*. + * + * Converts a @a T* to a @a B* (where @a T derives from @a B). + * The pointers are given and returned as @a void*. + */ + template <class B> + static void* converter (void* p) + { + B* b = reinterpret_cast<T*> (p); + return b; + } + + + /** + * @brief Converter function. + * @param p Pointer to convert. A @a B* converted to a @a void*. + * + * Converts a @a B* to a @a T* (where @a T derives from @a B). + * The pointers are given and returned as @a void*. + * Returns 0 if the conversion fails. + * + * Implementation note: to @c dynamic_cast @a B to @a T, @a B needs to have + * a vtable. If B doesn't have a vtable, then we don't attempt the + * conversion. (In principle, we could use is_virtual_base_of, and fall + * back to a static_cast if it's false. However, using is_virtual_base_of + * generates some nasty compilation warnings, so i'll avoid it for now.) + */ + template <class B> + static void* converterTo (void* p) + { + return converterToHelper<B> (p, boost::is_polymorphic<B>()); + } + + + // B has a vtable. Use dynamic_cast. + template <class B> + static void* converterToHelper (void* p, boost::true_type) + { + T* b = dynamic_cast<T*> (reinterpret_cast<B*> (p)); + return b; + } + + + // B doesn't have a vtable. Don't try to convert. + template <class B> + static void* converterToHelper (void* /*p*/, boost::false_type) + { + return 0; + } +}; + + +//=========================================================================== +// Initialization. +// Here we walk the class hierarchy, calling @a add_base for each base. + + +/** + * @brief Generic initializer for base @a B. + */ +template <class B> +struct BaseInfo_init +{ + template <class T> + static void init (BaseInfoImpl<T>& c, bool is_virtual) + { + // Here, we initialize the @a BaseInfo for @a T for base class @a B. + // First, we add the information for this base to the instance. + c.template add_base<B>(is_virtual); + + // Then we recurse on each possible base. + BaseInfo_init<typename Bases<B>::Base1>::init (c, is_virtual); + BaseInfo_init<typename Bases<B>::Base2>::init (c, is_virtual); + BaseInfo_init<typename Bases<B>::Base3>::init (c, is_virtual); + } +}; + + +/** + * @brief Dummy initializer. + */ +template <> +struct BaseInfo_init<NoBase> +{ + template <class T> + static void init (BaseInfoImpl<T>& /*c*/, bool /*is_virtual*/) + { + // This gets called when there is no base in a slot + // (signaled by the use of @a NoBase). + // This ends the recursion. + } +}; + + +/** + * @brief Initializer for virtual base @a B. + */ +template <class B> +struct BaseInfo_init<Virtual<B> > +{ + template <class T> + static void init (BaseInfoImpl<T>& c, bool /*is_virtual*/) + { + // Here, we initialize the @a BaseInfo for @a T for a virtual + // base class @a B. We recurse to the generic initializer + // for this base, with the @a is_virtual flag forced on. + BaseInfo_init<B>::init (c, true); + } +}; + + +/** + * @brief Constructor. + */ +template <class T> +BaseInfoImpl<T>::BaseInfoImpl () + : BaseInfoBase (SG::safe_clid<T>(), typeid(T)) +{ + // This starts the walk over the bases. + // We start with @a T itself. + // The virtual flag is initially false. + BaseInfo_init<T>::init (*this, false); +} + + +//=========================================================================== +// The @a BaseInfo wrapper class. +// This will statically hold a singleton instance of @a BaseInfoImpl +// (in the instance function). + + +/** + * @brief Cast to a base pointer. + * @param p The pointer to cast. + * @param clid ID of the class to which to cast. + * @return The pointer cast to the requested type, returned + * as a @a void*. @a clid must be known to be a base + * of @a T; otherwise, 0 will be returned. + */ +template <class T> +void* BaseInfo<T>::cast (T* p, CLID clid) +{ + return instance().cast (p, clid); +} + + +/** + * @brief Cast to a base pointer. + * @param p The pointer to cast. + * @param clid @a type_info of the class to which to cast. + * @return The pointer cast to the requested type, returned + * as a @a void*. @a tinfo must be known to be a base + * of @a T; otherwise, 0 will be returned. + */ +template <class T> +void* BaseInfo<T>::cast (T* p, const std::type_info& tinfo) +{ + return instance().cast (p, tinfo); +} + + +/** + * @brief Cast to a derived pointer. + * @param p The pointer to cast. + * @param clid ID of the class @a B from which to cast. + * @return The pointer cast to a @a T*. + * @a B must be known to be a base + * of @a T; otherwise, 0 will be returned. + * 0 will also be returned if the @a dynamic_cast fails. + */ +template <class T> +T* BaseInfo<T>::castTo (void* p, CLID clid) +{ + return reinterpret_cast<T*> (instance().castTo (p, clid)); +} + + +/** + * @brief Cast to a derived pointer. + * @param p The pointer to cast. + * @param clid @a type_info of the class @a B from which to cast. + * @return The pointer cast to a @a T*. + * @a B must be known to be a base + * of @a T; otherwise, 0 will be returned. + * 0 will also be returned if the @a dynamic_cast fails. + */ +template <class T> +T* BaseInfo<T>::castTo (void* p, const std::type_info& tinfo) +{ + return reinterpret_cast<T*> (instance().castTo (p, tinfo)); +} + + +#ifndef __REFLEX__ +/** + * @brief Return a function for casting to a base pointer. + * @param clid ID of the class to which to cast. + * @return A function to convert a pointer to a @c T to a pointer + * to the type identified by @a clid. + * @a clid must be known to be a base + * of @a T; otherwise, 0 will be returned. + */ +template <class T> +BaseInfoBase::castfn_t* BaseInfo<T>::castfn (CLID clid) +{ + return instance().castfn (clid); +} + + +/** + * @brief Return a function for casting to a base pointer. + * @param clid @a type_info of the class to which to cast. + * @return A function to convert a pointer to a @c T to a pointer + * to the type identified by @a tinfo. + * @a tinfo must be known to be a base + * of @a T; otherwise, 0 will be returned. + */ +template <class T> +BaseInfoBase::castfn_t* +BaseInfo<T>::castfn (const std::type_info& tinfo) +{ + return instance().castfn (tinfo); +} + + +/** + * @brief Return a function for casting to a derived pointer. + * @param clid ID of the class @a B from which to cast. + * @return A function to convert a pointer to a @c T to a pointer + * to a @a T. @a clid must be known to be a base + * of @a T; otherwise, 0 will be returned. + * 0 will also be returned if the @a dynamic_cast fails. + */ +template <class T> +BaseInfoBase::castfn_t* BaseInfo<T>::castfnTo (CLID clid) +{ + return instance().castfnTo (clid); +} + + +/** + * @brief Return a function for casting to a derived pointer. + * @param clid @a type_info of the class @a B from which to cast. + * @return A function to convert a pointer to a @c B to a pointer + * to a @T. @a tinfo must be known to be a base + * of @a T; otherwise, 0 will be returned. + * 0 will also be returned if the @a dynamic_cast fails. + */ +template <class T> +BaseInfoBase::castfn_t* +BaseInfo<T>::castfnTo (const std::type_info& tinfo) +{ + return instance().castfnTo (tinfo); +} +#endif + + +/** + * @brief Return the class IDs of all known bases of @a T (that + * have class IDs). The list will include @a T itself. + */ +template <class T> +std::vector<CLID> BaseInfo<T>::get_bases () +{ + return instance().get_bases(); +} + + +/** + * @brief Return the @c type_info's of all known bases of @a T. + * The list will include @a T itself. + */ +template <class T> +std::vector<const std::type_info*> +BaseInfo<T>::get_ti_bases () +{ + return instance().get_ti_bases(); +} + + +/** + * @brief Return true if @a clid is the ID of a class that + * is known to be a base of @a T. @a T is considered + * to be its own base for this purpose. + * @param clid The ID of the class to test. + */ +template <class T> +bool BaseInfo<T>::is_base (CLID clid) +{ + return instance().is_base (clid); +} + + +/** + * @brief Return true if @a tinfo is the @a std::type_info of a class that + * is known to be a base of @a T. @a T is considered + * to be its own base for this purpose. + * @param tinfo The @a std::type_info of the class to test. + */ +template <class T> +bool BaseInfo<T>::is_base (const std::type_info& tinfo) +{ + return instance().is_base (tinfo); +} + + +/** + * @brief Return true if @a clid is the ID of a class that + * is known to be a virtual base of @a T. (This will always + * be false for @a T itself.) + * @param clid The ID of the class to test. + */ +template <class T> +bool BaseInfo<T>::is_virtual (CLID clid) +{ + return instance().is_virtual (clid); +} + + +/** + * @brief Return true if @a tinfo is the @a std::type_info of a class that + * is known to be a virtual base of @a T. (This will always + * be false for @a T itself.) + * @param tinfo The @a std::type_info of the class to test. + */ +template <class T> +bool BaseInfo<T>::is_virtual (const std::type_info& tinfo) +{ + return instance().is_virtual (tinfo); +} + + +/** + * @brief Return the non-templated @c BaseInfoBase object for this type. + */ +template <class T> +const BaseInfoBase& BaseInfo<T>::baseinfo() +{ + return instance(); +} + + +/** + * @brief Return a reference to the (singleton) implementation object + * for this class. + */ +template <class T> +const BaseInfoImpl<T>& BaseInfo<T>::instance() +{ + BaseInfoImpl<T>* inst = s_instance.instance; + if (inst) + inst->maybeInit(); + return *inst; +} + + +/** + * @brief Constructor to get the singleton instance set up. + */ +template <class T> +BaseInfo<T>::instance_holder::instance_holder() +{ + static BaseInfoImpl<T> inst; + instance = &inst; +} + + +/// Declare the static member of @c BaseInfo. +template <class T> +typename BaseInfo<T>::instance_holder BaseInfo<T>::s_instance; + + +/** + * @brief Helper to get @c BaseInfo initialized. + */ +template <class T> +struct RegisterBaseInit +{ + RegisterBaseInit(); +}; + + +#ifndef __REFLEX__ +template <class T> +RegisterBaseInit<T>::RegisterBaseInit() +{ + BaseInfoBase::addInit(SG::safe_clid<T>(), &typeid(T), BaseInfo<T>::baseinfo); +} +#endif + + +/** + * @brief Helper to get @c BaseInfo initialized. + */ +template <class T> struct BaseInit { + static RegisterBaseInit<T> s_regbase; +}; +#ifndef __APPLE__ +template <class T> RegisterBaseInit<T> BaseInit<T>::s_regbase; +#endif + + +//********************************************************** +// SG_ADD_BASE and SG_ADD_COPY_CONVERSION implementation. + + +/** + * @brief Helper to get @c AddBaseInfo initialized. + */ +template <class D, class B> +struct RegisterAddBaseInit +{ + /// Add ourself to the init list. + RegisterAddBaseInit(); + + /// Init callback: add the new base to the BIB. + static const BaseInfoBase& doinit(); +}; + + +#ifndef __REFLEX__ +/** + * @brief Init callback: add the new base to the BIB. + */ +template <class D, class B> +const BaseInfoBase& RegisterAddBaseInit<D, B>::doinit() +{ + // B may either be the actual base class we want, + // or Virtual<BB>. Unwrap a surrounding Virtual<> if needed. + typedef typename BaseType<B>::type base_type; + bool is_virtual = BaseType<B>::is_virtual::value; + + // Look up the BIB. + SG::BaseInfoBase* bib = + const_cast<SG::BaseInfoBase*> (SG::BaseInfoBase::find (typeid(D))); + if (!bib) + bib = const_cast<SG::BaseInfoBase*> (&BaseInfo<D>::baseinfo()); + if (bib) { + // Add the new base to it. + SG::BaseInfoImpl<D>& impl = *static_cast<SG::BaseInfoImpl<D>*> (bib); + impl.template add_base<base_type> (is_virtual); + } + return *bib; +} + + +/** + * @brief Add ourself to the init list. + */ +template <class D, class B> +RegisterAddBaseInit<D, B>::RegisterAddBaseInit() +{ + BaseInfoBase::addInit(SG::safe_clid<D>(), &typeid(D), doinit); +} +#endif + + +/** + * @brief Helper to get @c AddBaseInfo initialized. + */ +template <class D, class B> struct AddBaseInit { + static RegisterAddBaseInit<D, B> s_regbase; +}; +#ifndef __APPLE__ +template <class D, class B> +RegisterAddBaseInit<D,B> AddBaseInit<D,B>::s_regbase; +#endif + + + +/** + * @brief Helper to get the copy conversion initialized. + */ +template <class D, class B> +struct RegisterAddCopyConversionInit +{ + /// Add ourself to the init list. + RegisterAddCopyConversionInit(); + + /// Init callback: xxx + static const BaseInfoBase& doinit(); +}; + + +#ifndef __REFLEX__ +/** + * @brief Init callback: add the new conversion to the BIB. + */ +template <class T, class C> +const BaseInfoBase& RegisterAddCopyConversionInit<T, C>::doinit() +{ + // Look up the BIB. + SG::BaseInfoBase* bib = + const_cast<SG::BaseInfoBase*> (SG::BaseInfoBase::find (typeid(T))); + if (!bib) + bib = const_cast<SG::BaseInfoBase*> (&BaseInfo<T>::baseinfo()); + if (bib) { + typedef typename C::target_type target_type; + bib->add_copy_conversion (SG::safe_clid<target_type>(), + typeid(target_type), + new C); + } + return *bib; +} + + +/** + * @brief Add ourself to the init list. + */ +template <class T, class C> +RegisterAddCopyConversionInit<T, C>::RegisterAddCopyConversionInit() +{ + BaseInfoBase::addInit(SG::safe_clid<T>(), &typeid(T), doinit); +} +#endif + + +/** + * @brief Helper to get @c AddBaseInfo initialized. + */ +template <class T, class C> struct AddCopyConversionInit { + static RegisterAddCopyConversionInit<T, C> s_regbase; +}; +#ifndef __APPLE__ +template <class T, class C> +RegisterAddCopyConversionInit<T,C> AddCopyConversionInit<T,C>::s_regbase; +#endif + + +} // namespace SG + diff --git a/Control/SGTools/SGTools/BuiltinsClids.h b/Control/SGTools/SGTools/BuiltinsClids.h new file mode 100644 index 0000000000000000000000000000000000000000..f478ae7709eac12269b130989591fc818ead8793 --- /dev/null +++ b/Control/SGTools/SGTools/BuiltinsClids.h @@ -0,0 +1,33 @@ +///////////////////////// -*- C++ -*- ///////////////////////////// + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// BuiltinsClids.h +// Header file for CLIDs for C++ builtins +// Author: S.Binet<binet@cern.ch> +/////////////////////////////////////////////////////////////////// +#ifndef SGTOOLS_BUILTINSCLIDS_H +#define SGTOOLS_BUILTINSCLIDS_H + +// STL includes +#include <string> + +// Gaudi includes + +// SGTools includes +#include "SGTools/CLASS_DEF.h" + +CLASS_DEF( char , 81926032 , 1 ) +CLASS_DEF( bool , 134610868 , 1 ) +CLASS_DEF( int , 244260744 , 1 ) +CLASS_DEF( unsigned int , 78410462 , 1 ) +CLASS_DEF( long , 136869678 , 1 ) +CLASS_DEF( unsigned long , 47413844 , 1 ) +CLASS_DEF( long long , 16133813 , 1 ) +CLASS_DEF( float , 225912587 , 1 ) +CLASS_DEF( double , 239989609 , 1 ) +CLASS_DEF( std::string , 116449351 , 1 ) + +#endif // !SGTOOLS_BUILTINSCLIDS_H diff --git a/Control/SGTools/SGTools/CLASS_DEF.h b/Control/SGTools/SGTools/CLASS_DEF.h new file mode 100755 index 0000000000000000000000000000000000000000..7f4d90607ee686c6b823b1c4e5d1f6b4fc34271d --- /dev/null +++ b/Control/SGTools/SGTools/CLASS_DEF.h @@ -0,0 +1,102 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef SGTOOLS_CLASS_DEF_H +#define SGTOOLS_CLASS_DEF_H +/** @file CLASS_DEF.h + * @brief macros to associate a CLID to a type + * + * @author Paolo Calafiura <pcalafiura@lbl.gov> + * $Id: CLASS_DEF.h,v 1.3 2009-01-15 19:07:29 binet Exp $ + */ + +#include "SGTools/ClassID_traits.h" +#include "CxxUtils/unused.h" +#include <boost/preprocessor/stringize.hpp> + +/** @def CLASS_DEF(NAME, CID , VERSION) + * @brief associate a clid and a version to a type + * eg + * @code + * CLASS_DEF(std::vector<Track*>,8901, 1) + * @endcode + * @param NAME type name + * @param CID clid + * @param VERSION not yet used + */ +#define CLASS_DEF(NAME, CID , VERSION) \ + template <> \ + struct ClassID_traits< NAME > { \ + typedef boost::is_base_and_derived<DataObject, NAME> isDObj_t; \ + BOOST_STATIC_CONSTANT(bool, s_isDataObject = isDObj_t::value); \ + typedef type_tools::Int2Type<s_isDataObject> is_DataObject_tag; \ + typedef type_tools::true_tag has_classID_tag; \ + static const CLID& ID() { static CLID c(CID); return c; } \ + static const std::string& typeName() { \ + static const std::string s_name = #NAME; \ + return s_name; \ + } \ + static Athena::PackageInfo packageInfo() { \ + static Athena::PackageInfo __pi( BOOST_PP_STRINGIZE(PACKAGE_VERSION_UQ) ); \ + return __pi; \ + } \ + static const std::type_info& typeInfo() { \ + return typeid (NAME); \ + } \ + typedef type_tools::true_tag has_version_tag; \ + BOOST_STATIC_CONSTANT(int, s_version = VERSION); \ + BOOST_STATIC_CONSTANT(bool, s_isConst = false); \ + }; \ + namespace detail { \ + const bool UNUSED(clidEntry_ ## CID) = \ + CLIDRegistry::addEntry<CID>(ClassID_traits< NAME >::typeName(), \ + ClassID_traits< NAME >::packageInfo(), \ + ClassName< NAME >::name()); \ + } + + +/** @def CLASS_DEF2(ARG1, ARG2, CID , VERSION) + * @brief hack to use instead of CLASS_DEF when type name contains a comma ',' + * eg + * @code + * CLASS_DEF2(map<int,string>,8900, 1) + * @endcode + * @param ARG1 type name (1st part) + * @param ARG2 type name (2nd part) + * @param CID clid + * @param VERSION not yet used + */ +#define CLASS_DEF2(ARG1, ARG2, CID , VERSION) \ + template <> \ + struct ClassID_traits< ARG1,ARG2 > { \ + typedef boost::is_base_and_derived<DataObject, ARG1, ARG2 > isDObj_t; \ + BOOST_STATIC_CONSTANT(bool, s_isDataObject = isDObj_t::value); \ + typedef type_tools::Int2Type<s_isDataObject> is_DataObject_tag; \ + typedef type_tools::true_tag has_classID_tag; \ + static const CLID& ID() { \ + static CLID c(CID); return c; \ + } \ + static const std::string& typeName() { \ + static const std::string s_name = #ARG1 "," #ARG2; \ + return s_name; \ + } \ + static const std::type_info& typeInfo() { \ + return typeid (ARG1,ARG2); \ + } \ + static Athena::PackageInfo packageInfo() { \ + return Athena::PackageInfo("Package-00-00-00"); \ + } \ + typedef type_tools::true_tag has_version_tag; \ + BOOST_STATIC_CONSTANT(int, s_version = VERSION); \ + BOOST_STATIC_CONSTANT(bool, s_isConst = false); \ + }; \ + namespace detail { \ + const bool UNUSED(clidEntry_ ## CID) = \ + CLIDRegistry::addEntry<CID> \ + (ClassID_traits< ARG1,ARG2 >::typeName(), \ + ClassID_traits< ARG1,ARG2 >::packageInfo(), \ + ClassName< ARG1,ARG2 >::name()); \ + } + +#endif // not SGTOOLS_CLASS_DEF_H diff --git a/Control/SGTools/SGTools/CLIDRegistry.h b/Control/SGTools/SGTools/CLIDRegistry.h new file mode 100755 index 0000000000000000000000000000000000000000..e0353cb1cd3ea494516daf6fbc93bc3e82665de2 --- /dev/null +++ b/Control/SGTools/SGTools/CLIDRegistry.h @@ -0,0 +1,115 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef SGTOOLS_CLIDREGISTRY_H +# define SGTOOLS_CLIDREGISTRY_H +/** @file CLIDRegistry.h + * @brief a static registry of CLID->typeName entries. NOT for general use. + * Use ClassIDSvc instead. + * + * @author Paolo Calafiura <pcalafiura@lbl.gov> - ATLAS Collaboration + *$Id: CLIDRegistry.h,v 1.2 2009-01-15 19:07:29 binet Exp $ + */ + +#include <vector> +#include <string> +#include <utility> /* pair */ +#include <boost/tuple/tuple.hpp> +#include <boost/static_assert.hpp> + +/* #define CLIDREG_DEBUG 1 */ +#ifdef CLIDREG_DEBUG + #include <iostream> +#endif + +#include "AthenaKernel/tools/AthenaPackageInfo.h" +#ifndef BOOST_HAS_STATIC_ASSERT +# include "CxxUtils/unused.h" +#endif + +namespace detail { + /// @name allowed class id range + //@{ + const unsigned long MINCLID = 256; + const unsigned long MAXCLID = 2147483647; ///< 2**31 - 1 + //@} +} + +/** @class CLIDRegistry + * @brief a static registry of CLID->typeName entries. NOT for general use. + * Use ClassIDSvc instead. + */ +class CLIDRegistry { +private: + typedef boost::tuple <unsigned long, + std::string, + Athena::PackageInfo, + std::string> tuple_t; + typedef std::vector< tuple_t > CLIDRegistryImpl; +public: + typedef CLIDRegistryImpl::const_iterator const_iterator; + + ///to be called by the CLASS_DEFS + template <unsigned long CLID> + static bool addEntry(const std::string& typeName, + const Athena::PackageInfo& pkgInfo, + const std::string& typeInfoName); + // static bool addEntry(unsigned long id, const std::string& typeName); + + /// allowed class id range (backward compatibility) + //@{ + static const unsigned long MINCLID; + static const unsigned long MAXCLID; + //@} + + /// registry accessors (used by ClassIDSvc) + //@{ + static const_iterator begin(); + static const_iterator end(); + /// are there new entries since last call? Does not move the entries ptr + static bool hasNewEntries(); + /// returns an iterator range over the entries added since last time + /// newEntries was called + static std::pair<const_iterator, const_iterator> newEntries(); + //@} + +private: + static CLIDRegistryImpl& registry(); +}; + + +//the drudgery below is to issue a compilation error when CLID is +//out of range +template <bool x> struct ERROR_CLID_out_of_CLIDRegistry_range; +template <> struct ERROR_CLID_out_of_CLIDRegistry_range<true>{}; + +#ifndef __GCCXML__ + +//<<<<<< INLINE MEMBER FUNCTIONS >>>>>> +template <unsigned long CLID> +bool CLIDRegistry::addEntry(const std::string& typeName, + const Athena::PackageInfo& pkgInfo, + const std::string& typeInfoName) { + //more drudgery +#ifdef BOOST_HAS_STATIC_ASSERT + static_assert (detail::MINCLID <= CLID && CLID <= detail::MAXCLID, + "CLID out of CLIDRegistry range"); +#else + UNUSED(typedef ::boost::static_assert_test< + sizeof(ERROR_CLID_out_of_CLIDRegistry_range< (bool)(detail::MINCLID <= CLID && CLID <= detail::MAXCLID) >) + > BOOST_JOIN(boost_static_assert_typedef_, __LINE__)); +#endif + + registry().push_back(tuple_t(CLID, typeName, pkgInfo, typeInfoName)); +#ifdef CLIDREG_DEBUG + std::cerr << "CLIDRegistry::addEntry: for CLID/type " + << CLID << '/' << typeName << " to registry " <<®istry() + <<std::endl; +#endif + return true; +} + +#endif + +#endif // SGTOOLS_CLIDREGISTRY_H diff --git a/Control/SGTools/SGTools/CallBackID.h b/Control/SGTools/SGTools/CallBackID.h new file mode 100755 index 0000000000000000000000000000000000000000..11df6021bcb47318181a1296bbf93a1a3d1d94d5 --- /dev/null +++ b/Control/SGTools/SGTools/CallBackID.h @@ -0,0 +1,65 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef SGTOOLS_CALLBACKID_H +#define SGTOOLS_CALLBACKID_H + +/***************************************************************************** + * + * CallBackID.h + * IOVSvc + * + * Author: Charles Leggett + * $Id: CallBackID.h,v 1.3 2005-11-08 22:01:30 ssnyder Exp $ + * + * Provides means to identify a callback function. + * + *****************************************************************************/ + +#ifndef ATHENAKERNEL_IOVSVCDEFS_H + #include "AthenaKernel/IOVSvcDefs.h" +#endif + +class CallBackID { +public: + CallBackID():m_offset(0),p_obj(0){}; + + template<typename T> + CallBackID(StatusCode (T::*updF)(IOVSVC_CALLBACK_ARGS), const T *obj) { + set(updF,obj); + } + + template<typename T> + void set(StatusCode (T::*updF)(IOVSVC_CALLBACK_ARGS), const T *obj); + + std::string name() const { return m_name; } + std::string objName() const { return m_objName; } + int offset() const { return m_offset; } + const void* ptr() const { return p_obj; } + + bool operator==(const CallBackID& cb) const { + return ( cb.m_offset == m_offset && cb.p_obj == p_obj ); + } + bool operator<(const CallBackID& cb) const { + if ( p_obj != cb.p_obj ) { + return ( p_obj < cb.p_obj ) ; + } else { + return ( m_offset < cb.m_offset ); + } + } + +private: + long m_offset; + const void* p_obj; + + std::string m_name; + std::string m_objName; + +}; + +#ifndef SGTOOLS_CALLBACKID_ICC + #include "SGTools/CallBackID.icc" +#endif + +#endif diff --git a/Control/SGTools/SGTools/CallBackID.icc b/Control/SGTools/SGTools/CallBackID.icc new file mode 100755 index 0000000000000000000000000000000000000000..72c251e9588659108fbc765e1ca34b8228720fb7 --- /dev/null +++ b/Control/SGTools/SGTools/CallBackID.icc @@ -0,0 +1,56 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef SGTOOLS_CALLBACKID_ICC +#define SGTOOLS_CALLBACKID_ICC + +/***************************************************************************** + * + * CallBackID.h + * IOVSvc + * + * Author: Charles Leggett + * $Id: CallBackID.icc,v 1.4 2005-11-08 22:01:30 ssnyder Exp $ + * + * Provides means to identify a callback function. + * + *****************************************************************************/ + +#ifndef _CPP_SSTREAM + #include <sstream> +#endif +#ifndef _STDIO_H + #include "stdio.h" +#endif +#ifndef GAUDIKERNEL_SYSTEM_H + #include "GaudiKernel/System.h" +#endif + +template<typename T> +void CallBackID::set( StatusCode (T::*updF)(IOVSVC_CALLBACK_ARGS), + const T *obj) +{ + union { + StatusCode (T::*updF)(IOVSVC_CALLBACK_ARGS); + long i; + } u; + u.updF = updF; + + p_obj = (void*) obj; + m_offset = u.i; + + // make allowances for various versions of gcc + #if (__GNUC__ < 3) + m_offset /= 0x10000; + #endif + + std::ostringstream ost; + ost << std::hex << "[0x" << (long)p_obj << "]+" << m_offset; + + m_objName = System::typeinfoName(typeid(*obj)); + m_name = m_objName + ost.str(); + +} + +#endif diff --git a/Control/SGTools/SGTools/ClassID_traits.h b/Control/SGTools/SGTools/ClassID_traits.h new file mode 100755 index 0000000000000000000000000000000000000000..ed282a221fb8ff0519ef113ca18335099d3d076d --- /dev/null +++ b/Control/SGTools/SGTools/ClassID_traits.h @@ -0,0 +1,106 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef SGTOOLS_CLASSID_TRAITS_H +#define SGTOOLS_CLASSID_TRAITS_H +/** @file ClassID_traits.h + * @brief a traits class that associates a CLID to a type T + * It also detects whether T inherits from Gaudi DataObject + * + * @author Paolo Calafiura <pcalafiura@lbl.gov> - ATLAS Collaboration + * $Id: ClassID_traits.h,v 1.3 2009-01-15 19:07:29 binet Exp $ + */ +#include <string> +#include <typeinfo> + +#include <boost/config.hpp> +#include <boost/type_traits/object_traits.hpp> +#include <boost/concept_check.hpp> +#include <boost/static_assert.hpp> + +#include "GaudiKernel/ClassID.h" +#include "GaudiKernel/DataObject.h" +#include "GaudiKernel/System.h" + +#include "SGTools/CLIDRegistry.h" +#include "SGTools/ClassName.h" + +#include "AthenaKernel/tools/type_tools.h" +#include "AthenaKernel/tools/AthenaPackageInfo.h" +#ifndef BOOST_HAS_STATIC_ASSERT +# include "CxxUtils/unused.h" +#endif + + + +template <bool x> struct ERROR_you_should_use_the_CLASS_DEF_macro_to_define_CLID_and_VERSION; +template <> struct ERROR_you_should_use_the_CLASS_DEF_macro_to_define_CLID_and_VERSION<true>{}; + +///internal use: issues a compilation error when condition B is false +#ifdef BOOST_HAS_STATIC_ASSERT +#define MY_STATIC_ASSERT( B ) \ + static_assert (B, "You should use the CLASS_DEF macro to define CLID and VERSION"); +#else +#define MY_STATIC_ASSERT( B ) \ + UNUSED(typedef ::boost::static_assert_test< \ + sizeof(ERROR_you_should_use_the_CLASS_DEF_macro_to_define_CLID_and_VERSION< (bool)( B ) >)>\ + BOOST_JOIN(boost_static_assert_typedef_, __LINE__)) +#endif + +/** @class ClassID_traits + * @brief a traits class that associates a CLID to a type T + * It also detects whether T inherits from Gaudi DataObject + */ +template <typename T> +struct ClassID_traits { + //default only works for DataObjects + typedef boost::is_base_and_derived<DataObject, T> isDObj_t; + ///flags whether T inherits from DataObject + BOOST_STATIC_CONSTANT(bool, s_isDataObject = isDObj_t::value); + + //default traits for class ID assignment + typedef type_tools::Int2Type<s_isDataObject> is_DataObject_tag; + + ///the CLID of T + static const CLID& ID() { + MY_STATIC_ASSERT(s_isDataObject); + return T::classID(); + } + + ///the demangled type name of T + static const std::string& typeName() { + MY_STATIC_ASSERT(s_isDataObject); + static const std::string s_tname = System::typeinfoName(typeid(T)); + return s_tname; + } + + ///the type id of T + static const std::type_info& typeId() { + MY_STATIC_ASSERT(s_isDataObject); + return typeid(T); + } + + ///the package name of this CLASSDEF (and BY CONVENTION of the data obj too!) + static Athena::PackageInfo packageInfo() { + MY_STATIC_ASSERT(s_isDataObject); + return Athena::PackageInfo("Package-00-00-00"); + } + + typedef type_tools::false_tag has_version_tag; + BOOST_STATIC_CONSTANT(int, s_version = 0); + + // Is this is true, these types will automatically be made + // const when added to StoreGate. + BOOST_STATIC_CONSTANT(bool, s_isConst = false); +}; + +#undef MY_STATIC_ASSERT + +#endif // not SGTOOLS_CLASSID_TRAITS_H + + + + + + diff --git a/Control/SGTools/SGTools/ClassName.h b/Control/SGTools/SGTools/ClassName.h new file mode 100644 index 0000000000000000000000000000000000000000..caa8f052f9503de027935a9df459eedd2c7f2beb --- /dev/null +++ b/Control/SGTools/SGTools/ClassName.h @@ -0,0 +1,45 @@ +// This file's extension implies that it's C, but it's really -*- C++ -*-. + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// $Id: ClassName.h,v 1.1 2009-01-15 19:07:29 binet Exp $ +/** + * @file SGTools/ClassName.h + * @author scott snyder + * @date Jul 2005 + * @brief An interface for getting the name of a class as a string. + */ + + +#ifndef SGTOOLS_CLASSNAME_H +#define SGTOOLS_CLASSNAME_H + + +#include <string> + + +/** + * @brief An interface for getting the name of a class as a string. + * + * This template class provides an interface for getting the name + * of a class as a string. By default, it uses @c typeinfoName + * from @c GaudiKernel, but it may be specialized to override + * the behavior for specific classes. + */ +template <class T> +class ClassName +{ +public: + /** + * @brief Return the name of class @c T as a string. + */ + static std::string name(); +}; + + +#include "SGTools/ClassName.icc" + + +#endif // not SGTOOLS_CLASSNAME_H diff --git a/Control/SGTools/SGTools/ClassName.icc b/Control/SGTools/SGTools/ClassName.icc new file mode 100644 index 0000000000000000000000000000000000000000..55e22f24897c17181a457113d36cd1298db54793 --- /dev/null +++ b/Control/SGTools/SGTools/ClassName.icc @@ -0,0 +1,85 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// $Id: ClassName.icc,v 1.1 2009-01-15 19:07:29 binet Exp $ +/** + * @file DataModel/ClassName.icc + * @author scott snyder + * @date Jul 2005 + * @brief An interface for getting the name of a class as a string. + * Implementation file. + */ + + +#include "GaudiKernel/System.h" + + +/** + * @brief Return the name of class @c T as a string. + */ +template <class T> +std::string ClassName<T>::name() +{ + return System::typeinfoName (typeid (T)); +} + +// /** +// * @brief Specialization of @c ClassName for @c std::vector. +// * +// * This overrides the default implementation of @c ClassName +// * to hide @c std::vector's second template parameter. +// */ +// #include <vector> +// template <class T> +// std::string ClassName<std::vector<T> >::name() +// { +// std::string out = "std::vector<"; +// out += ClassName<T>::name(); +// if (out[out.size()-1] == '>') +// out += ' '; +// out += '>'; +// return out; +// } + +// /** +// * @brief Specialization of @c ClassName for @c std::list. +// * +// * This overrides the default implementation of @c ClassName +// * to hide @c std::list's second template parameter. +// */ +// #include <list> +// template <class T> +// std::string ClassName<std::list<T> >::name() +// { +// std::string out = "std::list<"; +// out += ClassName<T>::name(); +// if (out[out.size()-1] == '>') +// out += ' '; +// out += '>'; +// return out; +// } + +// /** +// * @brief Specialization of @c ClassName for @c std::map. +// * +// * This overrides the default implementation of @c ClassName +// * to hide @c std::map's 4th template parameter (and optionally the 3rd too) +// */ +// #include <map> +// template <class K, class V, class C> +// std::string ClassName<std::map<K, V, C> >::name() +// { +// std::string out = "std::map<"; +// out += ClassName<K>::name()+ "," + ClassName<V>::name(); +// std::string comp = ClassName<C>::name(); +// if (comp.size() > 10 && comp.substr(0, 10) != "std::less<") { +// out += ","+ClassName<C>::name(); +// } +// if (out[out.size()-1] == '>') +// out += ' '; +// out += '>'; +// return out; +// } + + diff --git a/Control/SGTools/SGTools/DataBucket.h b/Control/SGTools/SGTools/DataBucket.h new file mode 100755 index 0000000000000000000000000000000000000000..e92da77a4023e7ab121488c89cfc0a9c4881f47d --- /dev/null +++ b/Control/SGTools/SGTools/DataBucket.h @@ -0,0 +1,124 @@ +///////////////////////// -*- C++ -*- ///////////////////////////// + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef SGTOOLS_DATABUCKET_H +#define SGTOOLS_DATABUCKET_H + +#include "SGTools/DataBucketBase.h" +#include "CxxUtils/override.h" + +//FIXME CLID is a tdef and can't be forward declared +#include "GaudiKernel/ClassID.h" +#include <memory> + +/** @class DataBucket + * @brief a wrapper inheriting from DataObject (via DataBucketBase) + * that takes ownership of a data object to be put in the DataStore + * @author ATLAS Collaboration + * $Id: DataBucket.h,v 1.10 2008-06-25 22:45:49 calaf Exp $ + **/ + +namespace SG { + class IRegisterTransient; + class CopyConversionBase; + + template <class T> + class DataBucket : public DataBucketBase { + + public: + + // CONSTRUCTORS: + + DataBucket(): m_ptr(0) {} //needed by the generic converters + DataBucket(T* data); +#if __cplusplus > 201100 + DataBucket(std::unique_ptr<T> data); +#endif + + // DESTRUCTOR: + + virtual ~DataBucket(); + + // DATAOBJECT METHODS --- FIXME not virtual! derived buckets? + const CLID& clID() const; + static const CLID& classID(); + + // return the pointer as a void* + virtual void* object() ATH_OVERRIDE { return m_ptr; } + + // Serialize the object for reading + // StreamBuffer& serialize(StreamBuffer& s); + // Serialize the object for writing + // StreamBuffer& serialize(StreamBuffer& s) const; + + + + // AUTOMATIC CONVERSION OF TYPES + operator T*() { return ptr(); } //FIXME can we do without? + operator const T*() const { return cptr(); } + + /** + * @brief Return the contents of the @c DataBucket, + * converted to type given by @a clid. Note that only + * derived->base conversions are allowed here. + * @param clid The class ID to which to convert. + * @param irt To be called if we make a new instance. + * @param isConst True if the object being converted is regarded as const. + */ + virtual void* cast (CLID clid, + IRegisterTransient* irt = 0, + bool isConst = true) const ATH_OVERRIDE; + + + /** + * @brief Return the contents of the @c DataBucket, + * converted to type given by @a std::type_info. Note that only + * derived->base conversions are allowed here. + * @param clid The @a std::type_info of the type to which to convert. + * @param irt To be called if we make a new instance. + * @param isConst True if the object being converted is regarded as const. + */ + virtual void* cast (const std::type_info& tinfo, + IRegisterTransient* irt = 0, + bool isConst = true) const ATH_OVERRIDE; + + /** + * @brief Return a new @c DataBucket whose payload has been cloned from the + * original one. + */ + virtual DataBucket* clone() const ATH_OVERRIDE; + + /** + * @brief Give up ownership of the @c DataBucket contents. + * This leaks the contents and it is useful mainly for error handling. + */ + virtual void relinquish() ATH_OVERRIDE{ m_ptr=0;} //LEAKS m_ptr + + /** + * If the held object derives from @c ILockable, call @lock() on it. + */ + virtual void lock() ATH_OVERRIDE; + + + protected: + T* ptr() { return m_ptr; } + const T* cptr() const { return m_ptr; } + + private: + T* m_ptr; //we own the thing now! + + /// Objects made by copy conversion. + typedef std::pair<const CopyConversionBase*, void*> ent_t; + typedef std::vector<ent_t> vec_t; + mutable vec_t m_cnvcopies; + + DataBucket (const DataBucket&); + DataBucket& operator= (const DataBucket&); + }; +} //end namespace SG +#include "SGTools/DataBucket.icc" + +#endif // SGTOOLS_DATABUCKET_H diff --git a/Control/SGTools/SGTools/DataBucket.icc b/Control/SGTools/SGTools/DataBucket.icc new file mode 100755 index 0000000000000000000000000000000000000000..62c04feb1d8320aa989a1672d3491d5c3ccfcc4b --- /dev/null +++ b/Control/SGTools/SGTools/DataBucket.icc @@ -0,0 +1,261 @@ +///////////////////////// -*- C++ -*- ///////////////////////////// + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef SGTOOLS_DATABUCKET_H +#include "SGTools/DataBucket.h" +#endif + +#include <boost/type_traits/cv_traits.hpp> +#include <boost/type_traits/transform_traits.hpp> +#include <boost/type_traits/is_integral.hpp> +#include <boost/type_traits/is_abstract.hpp> +#include <boost/type_traits/has_trivial_copy.hpp> + +#include "SGTools/ClassID_traits.h" +#include "SGTools/BaseInfo.h" +#include "SGTools/IRegisterTransient.h" +#include "AthenaKernel/ILockable.h" + +#if __cplusplus > 201100 +# include <type_traits> +namespace SG_STD_OR_BOOST = std; +#else +# include "boost/type_traits/is_polymorphic.hpp" +namespace SG_STD_OR_BOOST = boost; +#endif + + + +// Some helper functions. +namespace SG { + + +// If T is a DataObject, increment its reference count. +// The second parameter tells whether or not T is a DataObject. +template <class T> +void db_maybe_ref (T*, type_tools::false_tag) +{ +} +template <class T> +void db_maybe_ref (T* ptr, type_tools::true_tag) +{ + ptr->addRef(); +} + + +// Release the pointer PTR. +// If T is a DataObject, then decrement the reference count; +// otherwise, just delete it. +// The second parameter tells whether or not T is a DataObject. +template <class T> +void db_free_ptr (T* ptr, type_tools::false_tag) +{ + // std::cout << "db_free_ptr: deleting ptr @" << ptr << " of type " << ClassID_traits<T>::typeName() << std::endl; + delete ptr; +} +template <class T> +void db_free_ptr (T* ptr, type_tools::true_tag) +{ + // std::cout << "db_free_ptr: releasing ptr @" << ptr << " of type " << ClassID_traits<T>::typeName() << std::endl; + ptr->release(); +} + +// if T is abstract just return NULL and let clients deal with that +template <typename T> +SG::DataBucket<T>* db_clone_ptr (T*, boost::false_type) +{ return NULL; } + +// else use the copy constructor +template <typename T> +SG::DataBucket<T>* db_clone_ptr (T* ptr, boost::true_type) +{ return new SG::DataBucket<T>( new T(*ptr) ); } + +} // namespace SG + + +/////////////////////////////////////////////////////////////////////////////// +// CONSTRUCTORS +/////////////////////////////////////////////////////////////////////////////// +template <typename T> +SG::DataBucket<T>::DataBucket(T* data) + : m_ptr(data) +{ + // If T is a DataObject, increase the refcount. + typedef typename ClassID_traits<T>::is_DataObject_tag tag; + if (m_ptr) + SG::db_maybe_ref (m_ptr, tag()); +} + +#if __cplusplus > 201100 +template <typename T> +SG::DataBucket<T>::DataBucket(std::unique_ptr<T> data) + : m_ptr(data.release()) +{ + // If T is a DataObject, increase the refcount. + typedef typename ClassID_traits<T>::is_DataObject_tag tag; + if (m_ptr) + SG::db_maybe_ref (m_ptr, tag()); +} +#endif + +/////////////////////////////////////////////////////////////////////////////// +// DATAOBJECT +/////////////////////////////////////////////////////////////////////////////// +template <typename T> +const CLID& SG::DataBucket<T>::clID() const {return classID();} + +template <typename T> +const CLID& SG::DataBucket<T>::classID() { + typedef typename ::boost::remove_pointer<T>::type BareTp; + typedef typename ::boost::remove_const<BareTp>::type BareT; + return ClassID_traits<BareT>::ID(); +} + + +/** + * @brief Return the contents of the @c DataBucket, + * converted to type given by @a clid. Note that only + * derived->base conversions are allowed here. + * @param clid The class ID to which to convert. + * @param irt To be called if we make a new instance. + * @param isConst True if the object being converted is regarded as const. + */ +template <typename T> +void* +SG::DataBucket<T>::cast (CLID clid, + IRegisterTransient* irt /*= 0*/, + bool isConst /*=true*/) const +{ + void* ret = SG::BaseInfo<T>::cast (m_ptr, clid); + if (ret || !isConst) + return ret; + + // Is there a copy conversion available? + const CopyConversionBase* cc = SG::BaseInfo<T>::baseinfo().copy_conversion (clid); + if (cc) { + vec_t::iterator end = m_cnvcopies.end(); + for (vec_t::iterator it = m_cnvcopies.begin(); it != end; ++it) { + if (cc == it->first) { + cc->convertUntyped (m_ptr, it->second); + } + return it->second; + } + + void* newcont = cc->create(); + if (newcont) { + cc->convertUntyped (m_ptr, newcont); + m_cnvcopies.push_back (std::make_pair (cc, newcont)); + irt->registerTransient (newcont); + } + return newcont; + } + + return 0; +} + + +/** + * @brief Return the contents of the @c DataBucket, + * converted to type given by @a std::type_info. Note that only + * derived->base conversions are allowed here. + * @param clid The @a std::type_info of the type to which to convert. + * @param irt To be called if we make a new instance. + * @param isConst True if the object being converted is regarded as const. + */ +template <typename T> +void* SG::DataBucket<T>::cast (const std::type_info& tinfo, + IRegisterTransient* irt /*= 0*/, + bool isConst /*= true*/) const +{ + void* ret = SG::BaseInfo<T>::cast (m_ptr, tinfo); + if (ret || !isConst) + return ret; + + // Is there a copy conversion available? + const CopyConversionBase* cc = SG::BaseInfo<T>::baseinfo().copy_conversion (tinfo); + if (cc) { + vec_t::iterator end = m_cnvcopies.end(); + for (vec_t::iterator it = m_cnvcopies.begin(); it != end; ++it) { + if (cc == it->first) { + cc->convertUntyped (m_ptr, it->second); + } + return it->second; + } + + void* newcont = cc->create(); + if (newcont) { + cc->convertUntyped (m_ptr, newcont); + m_cnvcopies.push_back (std::make_pair (cc, newcont)); + irt->registerTransient (newcont); + } + return newcont; + } + + return 0; +} + +/** + * @brief Return a new @c DataBucket whose payload has been cloned from the + * original one. + */ +template <typename T> +SG::DataBucket<T>* SG::DataBucket<T>::clone() const +{ + if (!m_ptr) { return NULL; } + + typedef + boost::integral_constant< bool, !::boost::is_abstract<T>::value && + ::boost::has_trivial_copy<T>::value > + truth_type_t; + return SG::db_clone_ptr( m_ptr, truth_type_t() ); +} + +template <typename T> +SG::DataBucket<T>::~DataBucket() +{ + // Delete any copies. + vec_t::iterator end = m_cnvcopies.end(); + for (vec_t::iterator it = m_cnvcopies.begin(); it != end; ++it) { + it->first->destroy (it->second); + } + + // Either delete m_ptr or decrement the refcount, + // depending on whether or not T is a DataObject. + typedef typename ClassID_traits<T>::is_DataObject_tag tag; + if (m_ptr) + SG::db_free_ptr(m_ptr, tag()); +} + + +namespace { + + +template <class T> +void call_lock (T* p, SG_STD_OR_BOOST::true_type) +{ + ILockable* l = dynamic_cast<ILockable*> (p); + if (l) l->lock(); +} + + +template <class T> +void call_lock (T*, SG_STD_OR_BOOST::false_type) +{ +} + + +} // anonymous namespace + + +/** + * If the held object derives from @c ILockable, call @lock() on it. + */ +template <class T> +void SG::DataBucket<T>::lock() +{ + call_lock (m_ptr, typename SG_STD_OR_BOOST::is_polymorphic<T>::type()); +} + diff --git a/Control/SGTools/SGTools/DataBucketBase.h b/Control/SGTools/SGTools/DataBucketBase.h new file mode 100755 index 0000000000000000000000000000000000000000..40c7006973d67d48f50dc8cce4b992ccdfbd1d1e --- /dev/null +++ b/Control/SGTools/SGTools/DataBucketBase.h @@ -0,0 +1,92 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef SGTOOLS_DATABUCKETBASE_H +#define SGTOOLS_DATABUCKETBASE_H + +/** @class DataBucketBase + * @brief A non-templated base class for DataBucket, allows to access the + * transient object address as a void* + * @author ATLAS Collaboration + * $Id: DataBucketBase.h,v 1.7 2008-05-30 22:58:46 calaf Exp $ + **/ + + +#ifndef GAUDIKERNEL_DATAOBJECT_H + #include "GaudiKernel/DataObject.h" +#endif +#include <typeinfo> + +namespace SG { + class IRegisterTransient; +} + +class DataBucketBase : public DataObject +{ + + public: + + DataBucketBase() { }; + virtual ~DataBucketBase() { }; + virtual void* object() = 0; + + /** + * @brief Return the contents of the @c DataBucket, + * converted to type @a T. Note that only + * derived->base conversions are allowed here. + * @a T must have a valid Class ID for this to work. + * @param irt To be called if we make a new instance. + * @param isConst True if the object being converted is regarded as const. + */ + template <class T> T* cast (SG::IRegisterTransient* irt = 0, + bool isConst = true) const; + + /** + * @brief Return the contents of the @c DataBucket, + * converted to type given by @a clid. Note that only + * derived->base conversions are allowed here. + * @param clid The class ID to which to convert. + * @param irt To be called if we make a new instance. + * @param isConst True if the object being converted is regarded as const. + */ + virtual void* cast (CLID clid, + SG::IRegisterTransient* irt = 0, + bool isConst = true) const = 0; + + /** + * @brief Return the contents of the @c DataBucket, + * converted to type given by @a std::type_info. Note that only + * derived->base conversions are allowed here. + * @param clid The @a std::type_info of the type to which to convert. + * @param irt To be called if we make a new instance. + * @param isConst True if the object being converted is regarded as const. + */ + virtual void* cast (const std::type_info& tinfo, + SG::IRegisterTransient* irt = 0, + bool isConst = true) const = 0; + + /** + * @brief Return a new @c DataBucket whose payload has been cloned from the + * original one. + */ + virtual DataBucketBase* clone() const = 0; + + /** + * @brief Give up ownership of the @c DataBucket contents. + * This leaks the contents and it is useful mainly for error handling. + */ + virtual void relinquish() = 0; + + /** + * If the held object derives from @c ILockable, call @lock() on it. + */ + virtual void lock() = 0; +}; + + +#include "SGTools/DataBucketBase.icc" + + +#endif + diff --git a/Control/SGTools/SGTools/DataBucketBase.icc b/Control/SGTools/SGTools/DataBucketBase.icc new file mode 100755 index 0000000000000000000000000000000000000000..38f59c4d07d1c3bd246a3f0705181b1f7d3c96a6 --- /dev/null +++ b/Control/SGTools/SGTools/DataBucketBase.icc @@ -0,0 +1,35 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// $Id: DataBucketBase.icc,v 1.3 2008-04-08 16:05:32 ssnyder Exp $ +/** + * @file SGTools/DataBucketBase.icc + * @author scott snyder + * @date Nov 2005 + * @brief A non-templated base class for DataBucket, allows to access the + * transient object address as a void* + * Implementation file. + */ + +#include "SGTools/ClassID_traits.h" +#include "boost/type_traits/remove_const.hpp" +#include <typeinfo> + + +/** + * @brief Return the contents of the @c DataBucket, + * converted to type @a T. Note that only + * derived->base conversions are allowed here. + * @a T must have a valid Class ID for this to work. + * @param irt To be called if we make a new instance. + * @param isConst True if the object being converted is regarded as const. + */ +template <class T> +T* DataBucketBase::cast (SG::IRegisterTransient* irt /*= 0*/, + bool isConst /*= true*/) const +{ + return reinterpret_cast<T*> + (cast (typeid (typename boost::remove_const<T>::type), irt, isConst)); +} + diff --git a/Control/SGTools/SGTools/DataBucketTraitFwd.h b/Control/SGTools/SGTools/DataBucketTraitFwd.h new file mode 100644 index 0000000000000000000000000000000000000000..8a182bc3169e848a1b13da38560754e230bd2ed3 --- /dev/null +++ b/Control/SGTools/SGTools/DataBucketTraitFwd.h @@ -0,0 +1,36 @@ +// This file's extension implies that it's C, but it's really -*- C++ -*-. + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// $Id: DataBucketTraitFwd.h,v 1.2 2008-04-08 16:05:32 ssnyder Exp $ + +/** + * @file SGTools/DataBucketTrait.h + * @author scott snyder + * @date Mar, 2008 + * @brief Forward declaration of DataBucketTrait template. + */ + + +#ifndef SGTOOLS_DATABUCKETTRAITFWD_H +#define SGTOOLS_DATABUCKETTRAITFWD_H + + +namespace SG { + + + /** + * @brief Metafunction to find the proper @c DataBucket class for @c T. + * + * See in Storable_conversions.h for full documentation. + */ + template <class T, class U = T> + struct DataBucketTrait; + + +} // namespace SG + + +#endif // not SGTOOLS_DATABUCKETTRAITFWD_H diff --git a/Control/SGTools/SGTools/DataHandleBase.h b/Control/SGTools/SGTools/DataHandleBase.h new file mode 100644 index 0000000000000000000000000000000000000000..35bd0eb7bb51f39b3a34055c54201a262466f3bd --- /dev/null +++ b/Control/SGTools/SGTools/DataHandleBase.h @@ -0,0 +1,127 @@ +///////////////////////// -*- C++ -*- ///////////////////////////// + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// DataHandleBase.h +// Header file for class DataHandleBase +// Author: S.Binet<binet@cern.ch> +/////////////////////////////////////////////////////////////////// +#ifndef SGTOOLS_DATAHANDLEBASE_H +#define SGTOOLS_DATAHANDLEBASE_H 1 + +// STL includes +#include <string> + +// fwk includes +#include "AthenaKernel/IProxyDict.h" +#include "AthenaKernel/IResetable.h" + +// SGTools includes +#include "SGTools/DataProxy.h" +#include "SGTools/ProxyMap.h" + +// Forward declaration + + +/** + * @class DataHandleBase + * @brief an iterator over instances of a given type in an @c IProxyDict (such + * as StoreGateSvc). It d-casts and caches locally the pointed-at object, to + * speed-up subsequent accesses. + * It can be reset by the store for asynchronous updates (IOVSvc) + */ +class DataHandleBase : public IResetable +{ + + /////////////////////////////////////////////////////////////////// + // Public typedefs: + /////////////////////////////////////////////////////////////////// +public: + typedef std::string ID_type; + + /////////////////////////////////////////////////////////////////// + // Public methods: + /////////////////////////////////////////////////////////////////// +public: + + /// Default constructor: + DataHandleBase(); + + /// Copy constructor: + DataHandleBase( const DataHandleBase& rhs ); + + /// Assignment operator: + DataHandleBase& operator=( const DataHandleBase& rhs ); + + /// Constructor with parameters: + + DataHandleBase(SG::DataProxy* proxy); ///< + DataHandleBase(const SG::ConstProxyIterator& itr1, + const SG::ConstProxyIterator& itr2); + + /// Destructor: + virtual ~DataHandleBase(); + + /////////////////////////////////////////////////////////////////// + // Const methods: + /////////////////////////////////////////////////////////////////// + + /// \name validity checks + //@{ + bool isConst() const; + bool isInitialized() const; ///<weaker test but it does not touch the disk! + bool isSet() const { return isInitialized(); } + //@} + + /// Get the key string with which the current object was stored. + const std::string& key() const; + + StatusCode setState(SG::DataProxy* proxy) const; + StatusCode setState(IProxyDict* store, const ID_type& name) const; + + // Note: itr1 may be modified! + StatusCode setState(SG::ConstProxyIterator& itr1, + const SG::ConstProxyIterator& itr2) const; + + /// the CLID of the object we are bound to + virtual CLID clid() const =0; + + ///get the data object key (ID) + ID_type ID() const { return isInitialized() ? m_proxy->name() : "NONE"; } + + /////////////////////////////////////////////////////////////////// + // Non-const methods: + /////////////////////////////////////////////////////////////////// + + StatusCode setState(SG::DataProxy* proxy); + StatusCode setState(IProxyDict* store, const ID_type& name); + + /////////////////////////////////////////////////////////////////// + // Protected data: + /////////////////////////////////////////////////////////////////// +protected: + + /// iterator pointing at the beginning of the range of proxies + mutable SG::ConstProxyIterator m_itr; + + /// iterator pointing at the end of the range of proxies + mutable SG::ConstProxyIterator m_itrEnd; + + /// the proxy holding the object we are bound to + mutable SG::DataProxy* m_proxy; + + /// use the proxy-iterator or just the proxy ? + mutable bool m_useItr; + +}; + +/////////////////////////////////////////////////////////////////// +// Inline methods: +/////////////////////////////////////////////////////////////////// +//std::ostream& operator<<( std::ostream& out, const DataHandleBase& o ); + + + +#endif //> !SGTOOLS_DATAHANDLEBASE_H diff --git a/Control/SGTools/SGTools/DataProxy.h b/Control/SGTools/SGTools/DataProxy.h new file mode 100755 index 0000000000000000000000000000000000000000..abd00db60632ddb5e0fc433c0f6d331b88afbbff --- /dev/null +++ b/Control/SGTools/SGTools/DataProxy.h @@ -0,0 +1,261 @@ +// This file's extension implies that it's C, but it's really -*- C++ -*-. + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef SGTOOLS_DATAPROXY_H +#define SGTOOLS_DATAPROXY_H + +// includes +#include <string> +#include <set> +#include <list> +#include <typeinfo> +#include "GaudiKernel/IRegistry.h" +#include "GaudiKernel/ClassID.h" +#include "AthenaKernel/getMessageSvc.h" /*Athena::IMessageSvcHolder*/ +#include "SGTools/TransientAddress.h" +#include "SGTools/IRegisterTransient.h" +#include "SGTools/exceptions.h" + + +// forward declarations: +class DataObject; +class IConversionSvc; +class IResetable; +class IProxyDictWithPool; + +/** @class DataProxy + * @brief DataProxy provides the registry services for StoreGate + * @author ATLAS Collaboration + * $Id: DataProxy.h,v 1.11 2008-07-14 22:16:25 calaf Exp $ + **/ + +namespace SG { + class T2pMap; + + class DataProxy : public IRegistry, public IRegisterTransient + { + + public: + enum ErrNo {ALLOK, NOCNVSVC, NOIOA, CNVFAILED, T2PREGFAILED, NERRORS}; + //FIXME private typedef IRegistry::name_type name_type; + //FIXME private typedef IRegistry::id_type id_type; + typedef std::string name_type; + typedef std::string id_type; + typedef TransientAddress::TransientClidSet CLIDCont_t; + typedef TransientAddress::TransientAliasSet AliasCont_t; + + // Constructors + DataProxy(); // default constructor + + ///build from TransientAddress + DataProxy(TransientAddress* tAddr, + IConversionSvc* pDataLoader, + bool constFlag=false, bool resetOnly=true); + + ///build from DataObject + DataProxy(DataObject* dObject, + TransientAddress* tAddr, + bool constFlag=false, bool resetOnly=true); + + // Destructor + virtual ~DataProxy(); + + ///\name IRegistry implementation + //@{ + /// Add reference to object + virtual unsigned long addRef(); + + /// release reference to object + virtual unsigned long release(); + + /// return refCount + unsigned long refCount() const; + + /// Retrieve data object key == string + virtual const name_type& name() const { return m_tAddress->name(); } + + /// Retrieve data object key == string + /// duplicated for Gaudi folks does same as name() + virtual const id_type& identifier() const {return m_tAddress->name();} + + /// Retrieve DataObject + virtual DataObject* object() const { return m_dObject; } + + /// set an IOpaqueAddress + virtual void setAddress(IOpaqueAddress* ioa); + + /// Retrieve IOpaqueAddress + virtual IOpaqueAddress* address() const { return m_tAddress->address(); } + + /// set DataSvc (Gaudi-specific); do nothing for us + virtual IDataProviderSvc* dataSvc() const { return 0; } + //@} + + /// Retrieve TransientAddress + virtual TransientAddress* transientAddress() const { return m_tAddress; } + + /// access set of proxy aliases + const AliasCont_t& alias() const { return m_tAddress->alias(); } + + /// Other methods of DataProxy (not in Interface IRegistry): + + /// Reset DataObject and IOpaqueAddress: + void reset(); + + ///release or reset according to resetOnly flag + ///If force is true, then always release. + bool requestRelease(bool force = false); + + /// am I valid? + bool isValid() const; + + /// is the address valid? + bool isValidAddress() const; + + /// is the object valid? + bool isValidObject() const; + + /// set DataObject + void setObject(DataObject* obj); + + /// Access DataObject on-demand using conversion service + ///@throws runtime_error when converter fails + DataObject* accessData(); + + ErrNo errNo() const { return m_errno; } + + /// Retrieve clid + CLID clID() const { return m_tAddress->clID(); } + + /// Retrieve storage type + unsigned char svcType() const { return m_storageType; } + + /// Check if it is a const object + bool isConst() const { return m_const; } + + + /** + * @brief Mark this object as const. (Lock the object.) + * + * If the object held that derives from @c ILockable, then we also + * call @c lock on the object. + */ + void setConst(); + + + /// set the reset only flag: Clear Store will reset and not delete. + void resetOnly(const bool& flag) { m_resetFlag = flag; } + + /// Check reset only: + const bool& isResetOnly() const { return m_resetFlag; } + + bool bindHandle(IResetable* ir); + void unbindHandle(IResetable* ir); + + /// The following kept temporarily for backward compatibility: + const CLIDCont_t& transientID() const {return m_tAddress->transientID();} + + // cache the t2p + void setT2p(T2pMap* t2p); + + /** + * @brief Register a transient object in a t2p map. + * @param trans The object to register. + * + * (@c IRegisterTransient interface.) + */ + virtual void registerTransient (void* p); + + /// Set the store of which we're a part. + void setStore (IProxyDictWithPool* store) { m_store = store; } + + /// Return the store of which we're a part. + IProxyDictWithPool* store() const { return m_store; } + + private: + DataProxy(const DataProxy&); + DataProxy& operator=(const DataProxy&); + + TransientAddress* m_tAddress; + + unsigned long m_refCount; + + DataObject* m_dObject; + IConversionSvc* m_dataLoader; + + /// Is the proxy currently const? + bool m_const; + /// Was the proxy created as const? + bool m_origConst; + + unsigned char m_storageType; + + ///reset and not delete: default is true + bool m_resetFlag; + + /// list of bound DataHandles + std::list<IResetable*> m_handles; + + T2pMap* m_t2p; + Athena::IMessageSvcHolder m_ims; + + /// errno-style error code for accessData + enum ErrNo m_errno; + + /// The store of which we are a part. + IProxyDictWithPool* m_store; + + /// reset the bound DataHandles + void resetBoundHandles(); + + /** + * @brief Lock the data object we're holding, if any. + */ + void lock(); + }; + + ///cast the proxy into the concrete data object it proxies + //@{ + template<typename DATA> + DATA* DataProxy_cast(DataProxy* proxy); + + ///const pointer version of the cast + template<typename DATA> + const DATA* DataProxy_cast(const DataProxy* proxy) + { + return DataProxy_cast<DATA>(const_cast<DataProxy*>(proxy)); + } + + ///const ref version of the cast. @throws SG::ExcBadDataProxyCast. + template<typename DATA> + DATA DataProxy_cast(const DataProxy& proxy) + { + const DATA* result = DataProxy_cast<DATA>(&proxy); + if (!result) SG::throwExcBadDataProxyCast(proxy.clID(), typeid(DATA)); + return *result; + } + + /** + * @brief Try to get the pointer back from a @a DataProxy, + * converted to be of type @a clid. + * @param proxy The @a DataProxy. + * @param clid The ID of the class to which to convert. + * + * Only works if the held object is a @a DataBucket. + * Returns 0 on failure, + */ + void* DataProxy_cast(DataProxy* proxy, CLID clid); + //@} + +} //end namespace SG + +#include "SGTools/DataProxy.icc" + +#endif // SGTOOLS_DATAPROXY + + + + diff --git a/Control/SGTools/SGTools/DataProxy.icc b/Control/SGTools/SGTools/DataProxy.icc new file mode 100755 index 0000000000000000000000000000000000000000..bd96b242d153fad4a4083474ed2056506eb6e070 --- /dev/null +++ b/Control/SGTools/SGTools/DataProxy.icc @@ -0,0 +1,98 @@ +// This file's extension implies that it's C, but it's really -*- C++ -*-. + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/*************************************************************************** + implementation of DataProxy_cast operator + ----------------------------------------- + ATLAS Collaboration + ***************************************************************************/ + +// $Id: DataProxy.icc,v 1.6 2008-07-14 22:16:25 calaf Exp $ + +//<<<<<< INCLUDES >>>>>> +#include "SGTools/DataBucketBase.h" +#include "SGTools/ClassID_traits.h" +#include "SGTools/StorableConversions.h" +#ifndef NDEBUG +# include "AthenaKernel/getMessageSvc.h" +# include "GaudiKernel/MsgStream.h" +#endif + + +class DataObject; + +template <typename DATA> +DATA* SG::DataProxy_cast(SG::DataProxy* proxy) { + DATA* result(0); + + if (0 != proxy && proxy->isValid()) { + DataObject* pObject(proxy->accessData()); + + if (0 != pObject) { + const CLID& dataID(ClassID_traits<DATA>::ID()); + result = SG::Storable_cast<DATA>(pObject, true, proxy, proxy->isConst()); + if (0 == result) { + //if result is 0, probably DATA is neither the type the object was + // stored with, nor it inherits from it. + // Before giving up let's check its transient CLIDs + DataBucketBase* db(0); + if (proxy->transientAddress()->transientID(dataID) && + 0 != (db = dynamic_cast<DataBucketBase*>(pObject)) ) + { + //it is a symlink after all. Let's hard cast and keep our fingers Xed + // But first: if this is a non-const proxy, then the cast + // may have failed because it needed to go via a copying conversion + // that's not allowed for non-const objects. So try the conversion + // again as const; if that works, then don't do the hard cast. + if (!proxy->isConst() && + SG::Storable_cast<DATA>(pObject, true, proxy, true) != 0) + { +#ifndef NDEBUG + MsgStream gLog(Athena::getMessageSvc(), "SG::DataProxy_cast"); + gLog << MSG::WARNING + << "Request for a non-const object via copying conversion; " + << "requested CLID = " << dataID + << ", proxy primary ID is " << proxy->clID() << endreq ; +#endif + } + else { + // ok, hard cast. + result = static_cast<DATA*>(db->object()); + } + } + else { +#ifndef NDEBUG + MsgStream gLog(Athena::getMessageSvc(), "SG::DataProxy_cast"); + gLog << MSG::WARNING + << "Request for an invalid object; requested CLID = " + << dataID + << ", proxy primary ID is " << proxy->clID() << endreq ; +#endif + } //try symlink + } //result 0 + } else { // invalid pObject +#ifndef NDEBUG + MsgStream gLog(Athena::getMessageSvc(), "SG::DataProxy_cast"); + gLog << MSG::WARNING + << "this proxy " << MSG::hex << proxy + << MSG::dec << " has a NULL data object ptr" << endreq; +#endif + } + } else {// invalid proxy +#if 0 +#ifndef NDEBUG + MsgStream gLog(Athena::getMessageSvc(), "SG::DataProxy_cast"); + gLog << MSG::WARNING + << "this proxy " << MSG::hex << proxy + << MSG::dec << " [" << proxy->clID() << "/" << proxy->name() + << "] is in an invalid state" << endreq; +#endif +#endif + } + return result; +} + + diff --git a/Control/SGTools/SGTools/DataStore.h b/Control/SGTools/SGTools/DataStore.h new file mode 100755 index 0000000000000000000000000000000000000000..a0349765d6e72c32d66720fd01ae761408d5889e --- /dev/null +++ b/Control/SGTools/SGTools/DataStore.h @@ -0,0 +1,212 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef STOREGATE_DATASTORE_H +#define STOREGATE_DATASTORE_H +/** The Transient Store + * + * \author ATLAS Collaboration + **/ + + +#include "SGTools/ProxyMap.h" +#include "SGTools/T2pMap.h" +#include "SGTools/IProxyDictWithPool.h" +#include "AthenaKernel/DefaultKey.h" +#include "AthenaKernel/IProxyRegistry.h" +#include "CxxUtils/unordered_map.h" +#include "GaudiKernel/ClassID.h" +#include "GaudiKernel/StatusCode.h" +#include <boost/array.hpp> +#include <boost/type_traits/transform_traits.hpp> +#include <exception> +#include <list> +#include <vector> +#include <map> +#include <string> +#include <typeinfo> /*typeid*/ +#include <utility> /*std::pair*/ + + +class ISvcLocator; +class ISGAudSvc; +class MsgStream; +class IPageAccessControlSvc; + +namespace SG { + + class DataProxy; + + + /** + * @brief Hold DataProxy instances associated with a store. + * + * We have two ways of looking up a proxy. + * + * First, the proxy is stored by CLID/key in m_storeMap. This is a map + * indexed by CLID; the values are maps indexed by key. + * + * Second, m_keyMap stores proxies indexed by the hashed CLID/key. + * + * A proxy may be entered multiple times in the maps if there are + * symlinks or aliases. + * + * A proxy may be given to the store that has the hashed key set, + * but not the CLID/key. This is referred to as a `dummy' proxy. + * This can happen when we read a link to an object that's not + * described in the event's DataHeader. In this case, the proxy + * is entered only in the second map, m_keyMap. If we later look + * for a proxy by CLID/key and don't find it, we also look in m_keyMap + * to see if a dummy proxy has been entered there. If so, that point + * we fill in the CLID/key fields of the proxy and also enter + * it in m_storeMap. + */ + class DataStore : virtual public IProxyRegistry + { + + public: + + typedef IStringPool::sgkey_t sgkey_t; + typedef std::map<CLID, SG::ProxyMap> StoreMap; + typedef StoreMap::iterator StoreIterator; + typedef StoreMap::const_iterator ConstStoreIterator; + + typedef std::pair<SG::ConstProxyIterator, SG::ConstProxyIterator> constProxyRange; + + /** + * @brief Constructor. + * @param pool The string pool associated with this store. + */ + DataStore (IProxyDictWithPool& pool); + virtual ~DataStore(); + + void setStoreID(StoreID::type id) { m_storeID = id;} + virtual StoreID::type storeID() const { return m_storeID; } + + // If FORCE is true, then force deleting of all proxies, + // even if they would normally only be reset. + void clearStore(bool force = false, MsgStream* pmlog=0); + + ////////////////////////////////////////////////////////////////// + /// \name Implementation of IProxyRegistry. + //@{ + virtual StatusCode addToStore(const CLID& id, DataProxy* proxy); + /// return proxy for a given type/key pair + /// if key is empty returns the default proxy (currently last registered) + virtual DataProxy* proxy(const TransientAddress* tAddr) const; + //@} + virtual DataProxy* proxy(const CLID& id, + const std::string& key=SG::DEFAULTKEY) const; + + /// get proxy with given key. Returns 0 to flag failure + /// the key must match exactly (no wild carding for the default key) + SG::DataProxy* proxy_exact (sgkey_t sgkey) const; + + /// get proxy with given id. Returns 0 to flag failure + /// the key must match exactly (no wild carding for the default key) + virtual SG::DataProxy* proxy_exact(const CLID& id, + const std::string& key) const; + + /// remove proxy from store, unless proxy is reset only. + /// @param forceRemove remove the proxy no matter what + StatusCode removeProxy(DataProxy* proxy, bool forceRemove=false); + + /// add symlink to store: + StatusCode addSymLink(const CLID& linkid, DataProxy* proxy); + + /// add alias to store + StatusCode addAlias(const std::string& aliasKey, DataProxy* proxy); + + /// Count number of object of a given type in store + int typeCount(const CLID& id) const; + + /// Return an iterator over the StoreMap: + StatusCode tRange(ConstStoreIterator& f, ConstStoreIterator& e) const; + + /// Return an iterator over proxy for a given CLID: + StatusCode pRange(const CLID& id, SG::ConstProxyIterator& f, + SG::ConstProxyIterator& e) const; + + /// Return a list of all valid proxies in the store: + StatusCode proxyList(std::list<DataProxy*>& pList) const; + + + /// set IPageAccessControlSvc ptr in T2PMap + void setPac(IPageAccessControlSvc* pac) { m_t2p.setPac(pac); } + /// request an access control report, i.e. a list of proxies that have not been accessed since monitored + std::vector<DataProxy*> pacReport() const { return m_t2p.pacReport();} + + /// methods to query the T2PMap: + StatusCode t2pRegister(const void* const pTrans, DataProxy* const pPers); + void t2pRemove(const void* const pTrans); + + /// locate the persistent (proxy) for a given T* (void*): + DataProxy* locatePersistent(const void* const pTransient) const; + + // return list of keys associated with an object + void keys(const CLID& id, std::vector<std::string>& vkeys, + bool includeAlias, bool onlyValid); + + private: + + /// The string pool associated with this store. + IProxyDictWithPool& m_pool; + + StoreMap m_storeMap; + + /// Map of hashed sgkey -> DataProxy. + typedef SG::unordered_map<sgkey_t, DataProxy*> KeyMap_t; + KeyMap_t m_keyMap; + + StoreID::type m_storeID; + + // Map to hold the relation between transient and persistent object: + // we have changed to DataProxy as it is faster while recording + // to check if it already exists + T2pMap m_t2p; + + void setSGAudSvc() const; + mutable ISGAudSvc * m_pSGAudSvc; + mutable bool m_noAudSvc; + inline bool doAudit() const { + if (!m_noAudSvc) setSGAudSvc(); + return (m_pSGAudSvc); + } + + ISvcLocator* m_pSvcLoc; + StatusCode setSvcLoc(); + + + /** + * @brief Look for (and convert) a matching dummy proxy. + * @param id The CLID for which to search. + * @param key The key for which to search. + * + * In some cases, we may enter into the store a `dummy' proxy, + * which is identified only by the hashed CLID/key pair. + * (This can happen when we have a link to an object that's not + * listed in the DataHeader; in this case, we know the only hashed key + * and not the CLID or key.) + * + * This function is called after we fail to find a proxy by CLID/key. + * It additionally checks to see if there exists a dummy proxy with + * a hash matching this CLID/key. If so, the CLID/key are filled + * in in the proxy, and the proxy is entered in m_storeMap. + * + * Returns either the matching proxy or 0. + */ + DataProxy* findDummy (CLID id, const std::string& key); + }; + ////////////////////////////////////////////////////////////////// + inline void + DataStore::t2pRemove(const void* const pTrans) + { + m_t2p.t2pRemove(pTrans); + } + ////////////////////////////////////////////////////////////////// +} //end namespace SG + + +#endif // STOREGATE_DATASTORE + diff --git a/Control/SGTools/SGTools/IProxyDictWithPool.h b/Control/SGTools/SGTools/IProxyDictWithPool.h new file mode 100755 index 0000000000000000000000000000000000000000..b0e8807739d944eaf149c74da438050cd0eff478 --- /dev/null +++ b/Control/SGTools/SGTools/IProxyDictWithPool.h @@ -0,0 +1,58 @@ +// This file's extension implies that it's C, but it's really -*- C++ -*-. + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// $Id: IProxyDictWithPool.h,v 1.2 2008-04-18 03:18:24 ssnyder Exp $ +/** + * @file SGTools/IProxyDictWithPool.h + * @author scott snyder <snyder@bnl.gov> + * @date Mar, 2007 + * @brief Combine IProxyDict and IStringPool. + * + * Make a class that combines @c IProxyDict and @c IStringPool, + * so we can use both through a single pointer without having + * to dynamic_cast between them. + */ + + +#ifndef SGTOOLS_IPROXYDICTWITHPOOL_H +#define SGTOOLS_IPROXYDICTWITHPOOL_H + +#include "AthenaKernel/IProxyDict.h" +#include "SGTools/IStringPool.h" + + +/// Interface definition. +static const InterfaceID IID_IProxyDictWithPool ("IProxyDictWithPool", 1, 0); + + +/** + * @brief Combine IProxyDict and IStringPool. + */ +class IProxyDictWithPool + : public IProxyDict, + public IStringPool +{ +public: + /// Gaudi interface definition. + static const InterfaceID& interfaceID() { return IID_IProxyDictWithPool; } + + + /** + * @brief Test to see if the target of an ElementLink has moved. + * @param sgkey_in Original hashed key of the EL. + * @param index_in Original index of the EL. + * @param sgkey_out[out] New hashed key for the EL. + * @param index_out[out] New index for the EL. + * @return True if there is a remapping; false otherwise. + * + * The default implementation here always returns false. + */ + virtual bool tryELRemap (sgkey_t sgkey_in, size_t index_in, + sgkey_t& sgkey_out, size_t& index_out); +}; + + +#endif // not SGTOOLS_IPROXYDICTWITHPOOL_H diff --git a/Control/SGTools/SGTools/IRegisterTransient.h b/Control/SGTools/SGTools/IRegisterTransient.h new file mode 100644 index 0000000000000000000000000000000000000000..a503640e5e589a8c8570e7399cc808b1b6e5b4ae --- /dev/null +++ b/Control/SGTools/SGTools/IRegisterTransient.h @@ -0,0 +1,47 @@ +// This file's extension implies that it's C, but it's really -*- C++ -*-. + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// $Id: IRegisterTransient.h,v 1.2 2008-04-08 16:05:32 ssnyder Exp $ + +/** + * @file SGTools/IRegisterTransient.h + * @author scott snyder + * @date Mar, 2008 + * @brief Interface for registering a transient object in t2p map. + */ + + +#ifndef SGTOOLS_IREGISTERTRANSIENT +#define SGTOOLS_IREGISTERTRANSIENT + + +namespace SG { + + +/** + * @brief Interface for registering a transient object in t2p map. + * + * (See @c T2pMap.) + */ +class IRegisterTransient +{ +public: + /// Destructor. + virtual ~IRegisterTransient() {} + + + /** + * @brief Register a transient object in a t2p map. + * @param trans The object to register. + */ + virtual void registerTransient (void* trans) = 0; +}; + + +} // namespace SG + + +#endif // not SGTOOLS_IREGISTERTRANSIENT diff --git a/Control/SGTools/SGTools/IStringPool.h b/Control/SGTools/SGTools/IStringPool.h new file mode 100755 index 0000000000000000000000000000000000000000..cda84646227d91f0b09ed3423f43da23ddf0ebf6 --- /dev/null +++ b/Control/SGTools/SGTools/IStringPool.h @@ -0,0 +1,97 @@ +// This file's extension implies that it's C, but it's really -*- C++ -*-. + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// $Id: IStringPool.h,v 1.3 2008-09-03 17:19:10 ssnyder Exp $ +/** + * @file SGTools/IStringPool.h + * @author scott snyder <snyder@bnl.gov> + * @date Mar, 2007 + * @brief Abstract interface for looking up strings/CLIDs in a pool. + */ + + +#ifndef SGTOOLS_ISTRINGPOOL_H +#define SGTOOLS_ISTRINGPOOL_H + + +#include "AthenaKernel/sgkey_t.h" +#include "GaudiKernel/ClassID.h" +#include "GaudiKernel/IInterface.h" +#include <string> + + +/// Interface definition. +static const InterfaceID IID_IStringPool ("IStringPool", 1, 0); + + +/** + * @brief Abstract interface for looking up strings/CLIDs in a pool. + */ +class IStringPool +{ +public: + /// Gaudi interface definition. + static const InterfaceID& interfaceID() { return IID_IStringPool; } + + /// Destructor. + virtual ~IStringPool() {} + + /// Type of the keys. + typedef SG::sgkey_t sgkey_t; + + /** + * @brief Find the key for a string/CLID pair. + * @param str The string to look up. + * @param clid The CLID associated with the string. + * @return A key identifying the string. + * A given string will always return the same key. + * Will abort in case of a hash collision! + */ + virtual + sgkey_t stringToKey (const std::string& str, CLID clid) = 0; + + /** + * @brief Find the string corresponding to a given key. + * @param key The key to look up. + * @return Pointer to the string found, or null. + * We can find keys as long as the corresponding string + * was given to either @c stringToKey() or @c registerKey(). + */ + virtual + const std::string* keyToString (sgkey_t key) const = 0; + + /** + * @brief Find the string and CLID corresponding to a given key. + * @param key The key to look up. + * @param clid[out] The found CLID. + * @return Pointer to the string found, or null. + * We can find keys as long as the corresponding string + * was given to either @c stringToKey() or @c registerKey(). + */ + virtual + const std::string* keyToString (sgkey_t key, + CLID& clid) const = 0; + + /** + * @brief Remember an additional mapping from key to string/CLID. + * @param key The key to enter. + * @param str The string to enter. + * @param clid The CLID associated with the string. + * @return True if successful; false if the @c key already + * corresponds to a different string. + * + * This registers an additional mapping from a key to a string; + * it can be found later through @c lookup() on the string. + * Logs an error if @c key already corresponds to a different string. + */ + virtual + void registerKey (sgkey_t key, + const std::string& str, + CLID clid) = 0; +}; + + +#endif // not SGTOOLS_ISTRINGPOOL_H diff --git a/Control/SGTools/SGTools/ProxyMap.h b/Control/SGTools/SGTools/ProxyMap.h new file mode 100755 index 0000000000000000000000000000000000000000..088084653f393e08f1bc6365d1cbaeb8959c2338 --- /dev/null +++ b/Control/SGTools/SGTools/ProxyMap.h @@ -0,0 +1,31 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/*************************************************************************** + the DataStore proxy map + ---------------------------- + ATLAS Collaboration + ***************************************************************************/ + +// $Id: ProxyMap.h,v 1.2 2003-04-16 01:49:26 calaf Exp $ + +#ifndef SGTOOLS_PROXYMAP_H +#define SGTOOLS_PROXYMAP_H + +#ifndef _CPP_MAP + #include <map> +#endif +#ifndef _CPP_STRING + #include <string> +#endif + +namespace SG { + class DataProxy; + + typedef std::map<std::string, DataProxy*> ProxyMap; + typedef ProxyMap::iterator ProxyIterator; + typedef ProxyMap::const_iterator ConstProxyIterator; +} + +#endif // TOOLS_PROXYMAP_H diff --git a/Control/SGTools/SGTools/SGFolderItem.h b/Control/SGTools/SGTools/SGFolderItem.h new file mode 100755 index 0000000000000000000000000000000000000000..5847907fad54b341fc73a6c8632aad69a60ba302 --- /dev/null +++ b/Control/SGTools/SGTools/SGFolderItem.h @@ -0,0 +1,37 @@ +/* -*- C++ -*- */ + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/** @file SGFolderItem.h + * defines a class representing a folder item (data object clid/key) + */ +#ifndef SGTOOLS_FOLDERITEM_H +#define SGTOOLS_FOLDERITEM_H +#include <string> +#include "GaudiKernel/ClassID.h" +namespace SG { + /** @class SG::FolderItem + * @brief a Folder item (data object) is identified by the clid/key pair + * + * @author pcalafiura@lbl.gov - ATLAS Collaboration + * $Id: SGFolderItem.h,v 1.2 2008-03-26 22:36:54 calaf Exp $ + **/ + class FolderItem { + public: + FolderItem(CLID id=CLID_NULL, const std::string& key="") : m_id(id), m_key(key) {} + CLID id() const { return m_id; } + const std::string& key() const { return m_key; } + bool operator < (const FolderItem& rhs) const { + return ( id() < rhs.id() || + ( (id() == rhs.id()) && key() < rhs.key()) ); + } + bool isFolder() const; + private: + CLID m_id; + std::string m_key; + }; +} //ns SG + +#endif diff --git a/Control/SGTools/SGTools/SGIFolder.h b/Control/SGTools/SGTools/SGIFolder.h new file mode 100755 index 0000000000000000000000000000000000000000..e8b09a9a612362f88e06740f5f2f456bf1b42bf1 --- /dev/null +++ b/Control/SGTools/SGTools/SGIFolder.h @@ -0,0 +1,55 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef SGTOOLS_IFOLDER_H +#define SGTOOLS_IFOLDER_H + +#include <set> +#include <string> + +#ifndef GAUDIKERNEL_IALGTOOL_H + #include "GaudiKernel/IAlgTool.h" +#endif + +#include "SGTools/SGFolderItem.h" + +namespace SG { + /** @class SG::IFolder + * @brief a run-time configurable list of data objects + * + * @author pcalafiura@lbl.gov - ATLAS Collaboration + * $Id: SGIFolder.h,v 1.3 2008-04-24 00:55:21 calaf Exp $ + **/ + class IFolder : public virtual IAlgTool + { + public: + /// the list we manage + typedef std::set<FolderItem> ItemList; //FIXME would be nice to move to SG::Folder + + /// \name access the ItemList + //@{ + typedef ItemList::const_iterator const_iterator; + virtual const_iterator begin() const = 0; + virtual const_iterator end() const = 0; + //@} + ///add a data object identifier to the list + virtual StatusCode add(const std::string& typeName, const std::string& skey) = 0; + ///add a data object identifier to the list + virtual StatusCode add(const CLID& clid, const std::string& skey) = 0; + + ///clear the folder contents + virtual void clear() = 0; + + ///update list of items + virtual void updateItemList(bool checkValidCLID) = 0; + + + static const InterfaceID& interfaceID() { + static const InterfaceID _IID( "SG::IFolder", 1, 0 ); + return _IID; + } + }; +} //ns SG + +#endif diff --git a/Control/SGTools/SGTools/SGToolsDict.h b/Control/SGTools/SGTools/SGToolsDict.h new file mode 100755 index 0000000000000000000000000000000000000000..95e497b2fa15347dc7df858f720dc641b10f4798 --- /dev/null +++ b/Control/SGTools/SGTools/SGToolsDict.h @@ -0,0 +1,26 @@ +///////////////////////// -*- C++ -*- ///////////////////////////// + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef SGTOOLS_SGTOOLSDICT_H +#define SGTOOLS_SGTOOLSDICT_H + +#include <vector> +#include "SGTools/IProxyDictWithPool.h" +#include "SGTools/IStringPool.h" +#include "SGTools/DataBucket.h" +#include "SGTools/DataProxy.h" +#include "SGTools/BaseInfo.h" + +// Need to instantiate iterators +namespace SGToolsDict +{ + struct _tmp { + std::vector< SG::DataProxy*> m_sg_data_proxies; + std::vector<const SG::DataProxy*> m_const_sg_data_proxies; + }; +} + +#endif // not SGTOOLS_SGTOOLSDICT_H diff --git a/Control/SGTools/SGTools/SGVersionedKey.h b/Control/SGTools/SGTools/SGVersionedKey.h new file mode 100644 index 0000000000000000000000000000000000000000..f79c2f6d0e7d2cc9af1768df19e510048ca0c3bf --- /dev/null +++ b/Control/SGTools/SGTools/SGVersionedKey.h @@ -0,0 +1,104 @@ +/* -*- C++ -*- */ + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/** @file SGVersionedKey.h + * defines a StoreGateSvc key with a version number + */ +#ifndef SGTOOLS_VERSIONEDKEY_H +#define SGTOOLS_VERSIONEDKEY_H 1 +#include <iostream> +#include <string> +class StoreGateSvc; //our friend +class SGImplSvc; //our friend +namespace SG { + /** @class SG::VersionedKey + * @brief a StoreGateSvc key with a version number. + * Notice that StoreGate does not order multiple instances of an object with + * a given key by version number. A generic retrieve will always return + * the first version recorded. For example, if object ("MyKey",1) is recorded + * _before__ ("MyKey", 2) a sg.retrieve(pObj,"MyKey") will return ("MyKey",1). + * StoreGateSvc provides retrieveAllVersions and retrieveHighestVersion, + * which offer a better-defined behaviour. + * + * @author pcalafiura@lbl.gov - ATLAS Collaboration + * $Id: SGVersionedKey.h,v 1.4 2008-07-10 15:51:04 dquarrie Exp $ + **/ + class VersionedKey { + friend class ::StoreGateSvc; //call copyVK + friend class ::SGImplSvc; //call copyVK + public: + ///quickly determine whether a string has the right format to be a VK + static bool isVersionedKey(const char *); + ///quickly determine whether a string has the right format to be a VK + static bool isVersionedKey(const std::string&); + + /// version must be [0,99], 0 is the default version + VersionedKey(const char* key, unsigned char version); + /// version must be [0,99], 0 is the default version + VersionedKey(const std::string& key, unsigned char version); + + /// make a VersionedKey from vkey string. If vkey has the + /// VersionedKey format (;NN;key), it is simply copied, otherwise + /// it is taken to be the real key, and version=0 is assigned + explicit VersionedKey(const char* vkey); + /// make a VersionedKey from vkey string. If vkey has the + /// VersionedKey format (;NN;key), it is simply copied, otherwise + /// it is taken to be the real key, and version=0 is assigned + explicit VersionedKey(const std::string& vkey); + + /// copy constructor transfers ownership a la auto_ptr (hence rhs + /// is not really const). + VersionedKey(const VersionedKey& rhs); + + /// default constructor (invalid state, do not use) + VersionedKey(): m_versionKey(0) {} + + ~VersionedKey(); + + /// sets key to point to encoded key, and version to encoded version (0 is taken to mean default version). + void decode(char*& key, unsigned char& version) const; + /// convert underlying encoded m_versionKey C string + operator std::string() const { return std::string(m_versionKey); } + /// @returns version number + unsigned char version() const; + /// @returns base key + const char* key() const; + /// @returns access underlying encoded m_versionKey C string + const char* rawVersionKey() const { + return m_versionKey; + } + /// compare base keys + bool sameKey(const VersionedKey& vkey) const; + /// compare base keys + bool sameKey(const std::string& baseKey) const; + /// compare base keys + bool sameKey(const char* baseKey) const; + + private: + void encode(const char* key, unsigned char version); + void copyVK(const char* versionedKey); + static char separator() {return ';';} + static const char* formatString() {return ";%02u;%s";} + ///the encoded version/key. Mutable so that ownership can be transferred + ///in the copy constructor + mutable char* m_versionKey; + + VersionedKey& operator= (const VersionedKey&); + }; +} // ns SG + +/// sort according to highest key version +bool operator < (const SG::VersionedKey& lhs, const SG::VersionedKey& rhs); + +namespace SG { + inline + std::ostream& operator <<(std::ostream& ost, const SG::VersionedKey& k) { + return ost << k.rawVersionKey(); + // return ost.write(k.rawVersionKey(), strlen(k.rawVersionKey())); + } +} + +#endif diff --git a/Control/SGTools/SGTools/StlMapClids.h b/Control/SGTools/SGTools/StlMapClids.h new file mode 100644 index 0000000000000000000000000000000000000000..30fdadbf7318990238e93a732d9bc6b121ea371b --- /dev/null +++ b/Control/SGTools/SGTools/StlMapClids.h @@ -0,0 +1,39 @@ +///////////////////////// -*- C++ -*- ///////////////////////////// + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// StlMapClids.h +// Header file for CLIDs for various std::map<T,U> +// Author: S.Binet<binet@cern.ch> +/////////////////////////////////////////////////////////////////// +#ifndef SGTOOLS_STLMAPCLIDS_H +#define SGTOOLS_STLMAPCLIDS_H + +// STL includes +#include <map> +#include <string> +#include <vector> + +// Gaudi includes + +// SGTools includes +#include "SGTools/CLASS_DEF.h" + +CLASS_DEF2( std::map<int,int> , 103402598 , 1 ) +CLASS_DEF2( std::map<int,float> , 256222847 , 1 ) +CLASS_DEF2( std::map<int,double> , 235483215 , 1 ) + +CLASS_DEF2( std::map<std::string,int> , 170542827 , 1 ) +CLASS_DEF2( std::map<std::string,unsigned int> , 113556225 , 1 ) +CLASS_DEF2( std::map<std::string,float> , 193758082 , 1 ) +CLASS_DEF2( std::map<std::string,double> , 252602412 , 1 ) +CLASS_DEF2( std::map<std::string,std::string> , 143489258 , 1 ) + +CLASS_DEF2( std::map<std::string,std::vector<int> > , 181049313 , 1 ) +CLASS_DEF2( std::map<std::string,std::vector<unsigned int> > , 199376827 , 1 ) +CLASS_DEF2( std::map<std::string,std::vector<float> > , 259112316 , 1 ) +CLASS_DEF2( std::map<std::string,std::vector<double> > , 78422682 , 1 ) + +#endif // !SGTOOLS_STLMAPCLIDS_H diff --git a/Control/SGTools/SGTools/StlVectorClids.h b/Control/SGTools/SGTools/StlVectorClids.h new file mode 100644 index 0000000000000000000000000000000000000000..c67a3107080f6bcb12ccc8bd0247e7dc876fb9ff --- /dev/null +++ b/Control/SGTools/SGTools/StlVectorClids.h @@ -0,0 +1,52 @@ +///////////////////////// -*- C++ -*- ///////////////////////////// + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// StlVectorClids.h +// Header file for CLIDs for various std::vector<T> +// Author: S.Binet<binet@cern.ch> +/////////////////////////////////////////////////////////////////// +#ifndef SGTOOLS_STLVECTORCLIDS_H +#define SGTOOLS_STLVECTORCLIDS_H + +// STL includes +#include <vector> +#include <string> +#include <stdint.h> + +// Gaudi includes + +// SGTools includes +#include "SGTools/CLASS_DEF.h" + +CLASS_DEF( std::vector<bool> , 45822813 , 1 ) +CLASS_DEF( std::vector<short> , 35706084 , 1 ) +CLASS_DEF( std::vector<int> , 22592129 , 1 ) +CLASS_DEF( std::vector<long> , 6675975 , 1 ) +CLASS_DEF( std::vector<float> , 202242136 , 1 ) +CLASS_DEF( std::vector<double> , 219400222 , 1 ) +CLASS_DEF( std::vector<std::string> , 25884436 , 1 ) + +CLASS_DEF( std::vector<unsigned short> , 238793770 , 1 ) +CLASS_DEF( std::vector<unsigned int> , 177480351 , 1 ) +CLASS_DEF( std::vector<unsigned long> , 18868981 , 1 ) +CLASS_DEF( std::vector<unsigned long long> , 35119468 , 1 ) + +CLASS_DEF( std::vector<std::vector<char> > , 70698075 , 1 ) +CLASS_DEF( std::vector<std::vector<short> > , 24204906 , 1 ) +CLASS_DEF( std::vector<std::vector<int> > , 23262399 , 1 ) +CLASS_DEF( std::vector<std::vector<uint8_t> > , 126048273 , 1 ) +CLASS_DEF( std::vector<std::vector<unsigned short> > , 247252788 , 1 ) +CLASS_DEF( std::vector<std::vector<unsigned int> > , 213985193 , 1 ) +CLASS_DEF( std::vector<std::vector<unsigned long> > , 205717523 , 1 ) +CLASS_DEF( std::vector<std::vector<unsigned long long> > , 76977490 , 1 ) +CLASS_DEF( std::vector<std::vector<float> > , 258753314 , 1 ) +CLASS_DEF( std::vector<std::vector<double> > , 154043868 , 1 ) +CLASS_DEF( std::vector<std::vector<std::string> > , 101141770 , 1 ) + +CLASS_DEF( std::vector<std::vector<std::vector<int> > > , 85220325 , 1 ) +CLASS_DEF( std::vector<std::vector<std::vector<float> > > , 82469196 , 1 ) + +#endif // !SGTOOLS_STLVECTORCLIDS_H diff --git a/Control/SGTools/SGTools/StorableConversions.h b/Control/SGTools/SGTools/StorableConversions.h new file mode 100755 index 0000000000000000000000000000000000000000..f0838677e0d119b2e9c83458173a571217f952b4 --- /dev/null +++ b/Control/SGTools/SGTools/StorableConversions.h @@ -0,0 +1,262 @@ +// This file's extension implies that it's C, but it's really -*- C++ -*-. + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef SGTOOLS_STORABLECONVERSIONS_H +# define SGTOOLS_STORABLECONVERSIONS_H +/** @file StorableConversions.h + * @brief convert to and from a SG storable + * $Id: StorableConversions.h,v 1.13 2008-05-22 22:54:12 calaf Exp $ + * @author ATLAS Collaboration + **/ + +//<<<<<< INCLUDES >>>>>> +#include "SGTools/DataBucket.h" +#include "SGTools/ClassID_traits.h" +#include "SGTools/DataBucketTraitFwd.h" +#include "AthenaKernel/tools/type_tools.h" +#include "GaudiKernel/DataObject.h" + +#ifndef NDEBUG +# include "AthenaKernel/getMessageSvc.h" +# include "GaudiKernel/MsgStream.h" +#endif + +#include "boost/type_traits/is_same.hpp" +#include "boost/mpl/identity.hpp" +#include "boost/mpl/eval_if.hpp" +#include <memory> + +// +//<<<<<< FORWARD DECLARATIONS >>>>>> + +//<<<<<< FUNCTION DECLARATIONS >>>>>> +namespace SG { + + // put a dobj pointer in a bucket as appropriate + template <typename T> + DataObject* asStorable(T* pObject); + + // get a dobj pointer from a bucket as appropriate + template <typename T> + bool fromStorable(DataObject* pDObj, T*& pTrans, bool quiet=false, + IRegisterTransient* irt = 0, + bool isConst = true); + + template <typename T> + T* Storable_cast(DataObject* pDObj, bool quiet=true, + IRegisterTransient* irt = 0, + bool isConst = true) { + T* result; + return fromStorable(pDObj, result, quiet, irt, isConst) ? result : 0; + } + template <typename T> + const T* Storable_cast(const DataObject* pDObj, bool quiet=true, + IRegisterTransient* irt = 0, + bool isConst = true) { + return Storable_cast<T>(const_cast<DataObject*>(pDObj), quiet, irt, isConst); + } + + class bad_Storable_cast : public std::bad_cast {}; + template<typename T> + T& Storable_cast(const DataObject& dObj, bool quiet=true, + IRegisterTransient* irt = 0, + bool isConst = true) + { + T* result(0); + if (!fromStorable(const_cast<DataObject*>(&dObj), + result, quiet, irt, isConst)) throw bad_Storable_cast(); + return *(const_cast<T*>(result)); + } + + + /** + * @brief Try to get the pointer back from a @a DataObject, + * converted to be of type @a clid. + * @param pDObj The @a DataObject. + * @param clid The ID of the class to which to convert. + * @param irt To be called if we make a new instance. + * @param isConst True if the object being converted is regarded as const. + * + * Only works if the @a DataObject is a @a DataBucket. + * Returns 0 on failure, + */ + void* fromStorable(DataObject* pDObj, CLID clid, + IRegisterTransient* irt = 0, + bool isConst = true); + + + /** + * @brief Try to get the pointer back from a @a DataObject, + * converted to be of type @a clid. + * @param pDObj The @a DataObject. + * @param clid The ID of the class to which to convert. + * @param irt To be called if we make a new instance. + * @param isConst True if the object being converted is regarded as const. + * + * Only works if the @a DataObject is a @a DataBucket. + * Returns 0 on failure, + */ + void* Storable_cast(DataObject* pDObj, CLID clid, + IRegisterTransient* irt = 0, + bool isConst = true); + + /** + * @brief Try to get the pointer back from a @a DataObject, + * converted to be of type @a clid. + * @param pDObj The @a DataObject. + * @param clid The ID of the class to which to convert. + * @param irt To be called if we make a new instance. + * @param isConst True if the object being converted is regarded as const. + * + * Only works if the @a DataObject is a @a DataBucket. + * Returns 0 on failure, + */ + const void* Storable_cast(const DataObject* pDObj, CLID clid, + IRegisterTransient* irt = 0, + bool isConst = true); +} + +////////////////////////////////////////////////////////////////// +// implementation details + + +namespace SG { + + + /** + * @brief Metafunction to find the proper @c DataBucket class for @c T. + * + * Here's what we're trying to do. + * + * The default @c DataBucket class for @c T is @c SG::DataBucket\<T>. + * + * However, if @c T is a @c DataVector or @c DataList, then we want + * to use instead @c SG::DVLDataBucket\<T>. + * + * Further, if @c T derives from @c DataVector or @c DataList (as declared + * by @c SG_BASE), then we also want to use @c SG::DVLDataBucket\<T>. + * + * Further, we don't want this code to depend on @c DataVector + * or @c SG::DVLDataBucket. That behavior is enabled only + * by including the appropriate @c DataVector/@c DataList headers. + * + * So, we handle this with the following metafunction. + * (By saying that this is a `metafunction', it means that the result + * is given by the nested type @c type.) + * The @c T argument is the type we're testing, and @c U is the top-level + * type that was given to the original invocation of @c DataBucketTrait. + * If @c T has no bases (according to @c SG::Bases), we return + * @c SG::DataBucket\<U>. Otherwise, we apply ourselves recursively + * to the first base class. + * + * Other packages can then specialize this to change the behavior. + * + * We don't really try to handle multiple bases. In principle, + * we could loop over them. But it seems that that's not really needed, + * so i don't want to pull in the extra overhead unnecessarily. + * + * This class also defines a real static function init(). + * This is called from @c fromStorable. + * It can be used to force instantiation of reflection information. + */ + template <class T, class U /* = T*/> + struct DataBucketTrait + { + // The first base of @c T (or @c SG::NoBase). + typedef typename SG::BaseType<typename SG::Bases<T>::Base1>::type base1; + + // Test to see if it's valid. + typedef typename boost::is_same<base1, SG::NoBase>::type has_base; + + // This is what we'll return in the default (no base) case. + typedef boost::mpl::identity<SG::DataBucket<U> > deflt; + + // This is what we use to recursively check the base + typedef DataBucketTrait<base1, U> recurse; + + // Calculate the output. + // (Note that it's important to use @c eval_if here; otherwise, + // applying this to @c SG::NoBase won't work.) + typedef typename boost::mpl::eval_if<has_base, deflt, recurse>::type type; + + /// Initialization hook. A no-op by default. + static void init() {} + }; + + + // put a dobj pointer in a bucket as appropriate + template <typename T> + DataObject* asStorable(T* pObject) { + typedef typename DataBucketTrait<T>::type bucket_t; + return new bucket_t (pObject); + } + +#if __cplusplus > 201100 + template <typename T> + DataObject* asStorable(std::unique_ptr<T> pObject) { + typedef typename DataBucketTrait<T>::type bucket_t; + return new bucket_t (std::move(pObject)); + } +#endif + + // get a dobj pointer from a bucket as appropriate + //the DataObject must be a DataBucket<DATA>*. + + template <typename T> + bool fromStorable(DataObject* pDObj, T*& pTrans, + bool +#ifndef NDEBUG + quiet +#endif + , IRegisterTransient* irt, + bool isConst /*= true*/) + { + typedef typename DataBucketTrait<T>::type bucket_t; + DataBucketTrait<T>::init(); + + //check inputs + if (0 == pDObj) { + pTrans=0; +#ifndef NDEBUG + MsgStream gLog(Athena::getMessageSvc(), "SG::fromStorable"); + gLog << MSG::WARNING << "null input pointer " << endreq; +#endif + return false; + } + + // get T* from DataBucket: + SG::DataBucket<T>* bucketPtr = dynamic_cast<bucket_t*>(pDObj); + bool success(0 != bucketPtr); + if (success) + pTrans = *bucketPtr; + else { + // Try to use BaseInfo information to convert pointers. + DataBucketBase* b = dynamic_cast<DataBucketBase*>(pDObj); + if (b) { + pTrans = b->template cast<T> (irt, isConst); + if (pTrans) + success = true; + } + } + +#ifndef NDEBUG + if (!quiet && !success) { + MsgStream gLog(Athena::getMessageSvc(), "SG::fromStorable"); + gLog << MSG::WARNING + << "can't convert stored DataObject " << pDObj + << " to type (" + << ClassID_traits<T>::typeName() + << ")\n Unless you are following a symlink," + << " it probably means you have a duplicate " + << "CLID = " << pDObj->clID() + << endreq; + } +#endif + return success; + } +} + +#endif // SGTOOLS_STORABLECONVERSIONS_H diff --git a/Control/SGTools/SGTools/StringPool.h b/Control/SGTools/SGTools/StringPool.h new file mode 100755 index 0000000000000000000000000000000000000000..3897312a354a2faf545d5e497888ac28c5ddede8 --- /dev/null +++ b/Control/SGTools/SGTools/StringPool.h @@ -0,0 +1,114 @@ +// This file's extension implies that it's C, but it's really -*- C++ -*-. + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// $Id: StringPool.h,v 1.4 2008-09-03 17:19:10 ssnyder Exp $ +/** + * @file SGTools/StringPool.h + * @author scott snyder + * @date Mar 2007 + * @brief Maintain a mapping of strings to 64-bit ints. + * + * We map from strings to integer keys using a hash function. + * We keep a table of hashed strings so that we can later return the string + * given the key. + * We allow registering additional key->string mappings as well, as long + * as there aren't collisions. + * We also keep an auxiliary int that gets hashed along with the string. + */ + +#ifndef SGTOOLS_STRINGPOOL_H +#define SGTOOLS_STRINGPOOL_H + +#include <stdint.h> +#include <string> + +namespace SG { + +class StringPoolImpl; + +class StringPool +{ +public: + /// Type of the integer keys. + typedef uint32_t sgkey_t; + + /// Type of auxiliary data. + typedef unsigned int sgaux_t; + + /// Number of bits we'll use in the keys. + /// Leave a few spare bits in case we want to overload them for flags later. + static const int sgkey_t_nbits = 30; + static const sgkey_t sgkey_t_max = + (static_cast<sgkey_t>(1) << sgkey_t_nbits) - 1; + + /// Constructor. + StringPool(); + + /// Destructor. + ~StringPool(); + + /** + * @brief Find the key for a string. + * @param str The string to look up. + * @param aux Auxiliary data to include along with the string. + * @return A key identifying the string. + * A given string will always return the same key. + * Will abort in case of a hash collision! + */ + sgkey_t stringToKey (const std::string& str, sgaux_t aux = 0); + + /** + * @brief Find the string corresponding to a given key. + * @param key The key to look up. + * @return Pointer to the string found, or null. + * We can find keys as long as the corresponding string + * was given to either @c stringToKey() or @c registerKey(). + */ + const std::string* keyToString (sgkey_t key) const; + + /** + * @brief Find the string corresponding to a given key. + * @param key The key to look up. + * @param aux[out] Auxiliary data associated with the key. + * @return Pointer to the string found, or null. + * We can find keys as long as the corresponding string + * was given to either @c stringToKey() or @c registerKey(). + */ + const std::string* keyToString (sgkey_t key, sgaux_t& aux) const; + + /** + * @brief Remember an additional mapping from key to string. + * @param key The key to enter. + * @param str The string to enter. + * @param aux Auxiliary data to include along with the string. + * @return True if successful; false if the @c key already + * corresponds to a different string. + * + * This registers an additional mapping from a key to a string; + * it can be found later through @c lookup() on the string. + */ + bool registerKey (sgkey_t key, + const std::string& str, + sgaux_t aux = 0); + + /** + * @brief Debugging dump. Write to cout. + */ + void dump () const; + +private: + StringPoolImpl* m_impl; + + // Don't allow copying. + StringPool (const StringPool&); + StringPool& operator= (const StringPool&); +}; + + +} // namespace SG + + +#endif // not SGTOOLS_STRINGPOOL_H diff --git a/Control/SGTools/SGTools/T2pMap.h b/Control/SGTools/SGTools/T2pMap.h new file mode 100755 index 0000000000000000000000000000000000000000..94e95ac9a51587fe197b57e5c68670be0fa0f827 --- /dev/null +++ b/Control/SGTools/SGTools/T2pMap.h @@ -0,0 +1,72 @@ +/* -*- C++ -*- */ + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef SGTOOLS_T2PMAP_H +#define SGTOOLS_T2PMAP_H + +#include "CxxUtils/unordered_map.h" +#include "SGTools/ptrhash.h" +#include <utility> +#include <vector> +#include "AthenaKernel/IPageAccessControlSvc.h" + +namespace SG { + +class DataProxy; + +class T2pMap { + + public: + + typedef SG::unordered_map<const void*, DataProxy*, ptrhash> t2p; + + // constructor + T2pMap(IPageAccessControlSvc* pac=0) : m_pac(pac) { }; + + // Destructor + ~T2pMap() { }; + + // associate a void* (T*) with a proxy + bool t2pRegister(const void* const pTrans, DataProxy* const pPers) { + bool success(m_t2p.insert (std::make_pair (pTrans, pPers)) . second); + if (m_pac) m_pac->controlPage(pTrans); + return success; + } + + // locate a proxy in t2p map + DataProxy* locatePersistent(const void* const pTransient) const { + t2p::const_iterator i = m_t2p.find(pTransient); + + if (i == m_t2p.end()) + return 0; + else + return i->second; + } + + // clear the t2p map + void clear() { + m_t2p.clear(); + } + + // remove a void* from t2p + void t2pRemove(const void* const pTrans) { + m_t2p.erase(pTrans); + } + + /// set IPageAccessControlSvc ptr in T2PMap + void setPac(IPageAccessControlSvc* pac) { m_pac=pac; } + /// request an access control report, i.e. a list of proxies that have not been accessed since under control; + std::vector<DataProxy*> pacReport() const; + + + private: + IPageAccessControlSvc* m_pac; + t2p m_t2p; + +}; + +} +#endif diff --git a/Control/SGTools/SGTools/TransientAddress.h b/Control/SGTools/SGTools/TransientAddress.h new file mode 100755 index 0000000000000000000000000000000000000000..81ecf52bf3326932533cc7d3cc7585956e20d214 --- /dev/null +++ b/Control/SGTools/SGTools/TransientAddress.h @@ -0,0 +1,280 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef SGTOOLS_TRANSIENTADDRESS_H +#define SGTOOLS_TRANSIENTADDRESS_H + +///< includes: +#include <string> +#include <set> + + +///< Gaudi includes: +#include "SGTools/IStringPool.h" +#include "GaudiKernel/ClassID.h" +#include "AthenaKernel/StoreID.h" + +///< forward declarations: +class IOpaqueAddress; +class IAddressProvider; + +namespace SG { + + class TransientAddress + { + + public: + + typedef std::set<CLID> TransientClidSet; + typedef std::set<std::string> TransientAliasSet; + typedef IStringPool::sgkey_t sgkey_t; + + ///< Default Constructor + TransientAddress(); + + ///< Construct from clid and string key: + TransientAddress(const CLID& id, const std::string& key); + + ///< Construct from clid, key and IOpaqueAddress + TransientAddress(const CLID& id, const std::string& key, + IOpaqueAddress* addr, bool clearAddress = true); + + ///< Destructor + virtual ~TransientAddress(); + + /// Set the CLID / key. + /// This will only succeed if the clid/key are currently clear. + void setID (CLID id, const std::string& key); + + ///< Reset + void reset(); + + ///< Retrieve IOpaqueAddress + virtual IOpaqueAddress* address() const; + + ///< set IOpaqueAddress + virtual void setAddress(IOpaqueAddress* pAddress); + + ///< Retrieve primary clid + CLID clID() const; + + ///< Retrieve string key: + const std::string& name() const; + + ///< Get the primary (hashed) SG key. + sgkey_t sgkey() const; + + ///< Set the primary (hashed) SG key. + void setSGKey (sgkey_t sgkey); + + ///< check if it is a transient ID (primary or symLinked): + bool transientID (const CLID& id) const; + + ///< set transient CLID's + void setTransientID(const CLID& id); + + ///< get transient CLID's + const TransientClidSet& transientID() const; + + ///< set alias' + void setAlias(const std::string& key); + + ///< set alias' + void setAlias(const std::set<std::string>& keys); + + /// remove alias from proxy + bool removeAlias(const std::string& key); + + ///< get transient alias + const TransientAliasSet& alias() const; + + ///< set the clearAddress flag: IOA will not be deleted in proxy + void clearAddress(const bool& flag); + + ///< this sets the flag whether to consult the provider to update + /// this transient address if the IOA is not valid. + void consultProvider(const bool& flag); + + ///< Check the validity of the Transient Address. + bool isValid(); + + ///< cache the pointer to the Address provider which can update + ///< this transient address + IAddressProvider* provider() const; + StoreID::type storeID() const; + void setProvider(IAddressProvider* provider, StoreID::type storeID); + + private: + + ///< clid of the concrete class (persistent clid) + CLID m_clid; + + ///< string key of this object + std::string m_name; + + ///< all transient clids. They come from symlinks + TransientClidSet m_transientID; + + ///< all alias names for a DataObject. They come from setAlias + TransientAliasSet m_transientAlias; + + ///< IOpaqueAddress: + IOpaqueAddress* m_address; + + ///< Controls if IOpaqueAddress should be deleted: + bool m_clearAddress; + + ///< Control whether the Address Provider must be consulted + bool m_consultProvider; + + ///< AddressProvider + IAddressProvider* m_pAddressProvider; + + ///< Store type, needed by updateAddress + StoreID::type m_storeID; + + ///< (hashed) SG key for primary clid / key. + sgkey_t m_sgkey; + }; + ///////////////////////////////////////////////////////////////////// + // inlined code: + ///////////////////////////////////////////////////////////////////// + + // Reset the TransientAddress + inline + void TransientAddress::reset() + { + if (m_clearAddress) setAddress(0); + } + + /// Retrieve IOpaqueAddress + inline + IOpaqueAddress* TransientAddress::address() const + { + return m_address; + } + + /// Retrieve clid + inline + CLID TransientAddress::clID() const + { + return m_clid; + } + + /// Return StoreGate key + inline + const std::string& TransientAddress::name() const + { + return m_name; + } + + /// Get the primary (hashed) SG key. + inline + TransientAddress::sgkey_t TransientAddress::sgkey() const + { + return m_sgkey; + } + + /// Set the primary (hashed) SG key. + inline + void TransientAddress::setSGKey (sgkey_t sgkey) + { + m_sgkey = sgkey; + } + + /// check if it is a transient ID: + inline + bool TransientAddress::transientID(const CLID& id) const + { + return 0 != m_transientID.count(id); + } + + /// set transient CLID's + inline + void TransientAddress::setTransientID(const CLID& id) + { + m_transientID.insert(id); + } + + /// get transient CLID's + inline + const TransientAddress::TransientClidSet& TransientAddress::transientID() const + { + return m_transientID; + } + + /// set transient Alias' + inline + void TransientAddress::setAlias(const std::string& key) + { + m_transientAlias.insert(key); + } + + /// set transient Alias' + inline + void TransientAddress::setAlias(const std::set<std::string>& keys) + { + m_transientAlias = keys; + } + + /// remove alias + inline bool TransientAddress::removeAlias(const std::string& key) + { + return (m_transientAlias.erase(key) == 1) ? true:false; + } + + /// get transient Alias' + inline + const TransientAddress::TransientAliasSet& TransientAddress::alias() const + { + return m_transientAlias; + } + + /// set the clearAddress flag: IOA will not be deleted in proxy + inline + void TransientAddress::clearAddress(const bool& flag) + { + m_clearAddress = flag; + } + + inline + void TransientAddress::consultProvider(const bool& flag) + { + m_consultProvider = flag; + } + + ///< cache the pointer to the Address provider which can update + ///< this transient address + inline + IAddressProvider* TransientAddress::provider() const + { + return m_pAddressProvider; + } + inline + StoreID::type TransientAddress::storeID() const + { + return m_storeID; + } + + inline + void TransientAddress::setProvider(IAddressProvider* provider, + StoreID::type storeID) + { + m_pAddressProvider = provider; + m_consultProvider = true; + m_storeID=storeID; + } +} //end namespace SG + +#endif // STOREGATE_TRANSIENTADDRESS + + + + + + + + + + diff --git a/Control/SGTools/SGTools/crc64.h b/Control/SGTools/SGTools/crc64.h new file mode 100755 index 0000000000000000000000000000000000000000..d9a017ca7db4d1030dcc27b87686bce43ea0e2a8 --- /dev/null +++ b/Control/SGTools/SGTools/crc64.h @@ -0,0 +1,56 @@ +// This file's extension implies that it's C, but it's really -*- C++ -*-. +/** + * @file SGTools/crc64.h + * @author scott snyder, originally from David T. Jones + * @date Mar 2007 + * @brief A CRC-64 implementation. + */ + +#ifndef SGTOOLS_CRC64_H +#define SGTOOLS_CRC64_H + + +#include <string> +#include <stdint.h> + + +namespace SG { + + +/** + * @brief Find the CRC-64 of a string. + * @param str The string to hash. + */ +uint64_t crc64 (const std::string& str); + + +/** + * @brief Extend a previously-calculated CRC to include an int. + * @param crc The previously-calculated CRC. + * @param x The integer to add. + * @return The new CRC. + */ +uint64_t crc64addint (uint64_t crc, unsigned int x); + + +/** + * @brief Format a CRC-64 as a string. + * @param crc The CRC to format. + */ +std::string crc64format (uint64_t crc); + + +/** + * @brief Return a CRC-64 digest of a string. + * @param str The string to hash. + * @return The CRC-64 digest of the string. + * This is the hash code, expressed as hex as a string. + */ +std::string crc64digest (const std::string& str); + + +} // namespace SG + + + +#endif // not SGTOOLS_CRC64_H diff --git a/Control/SGTools/SGTools/exceptions.h b/Control/SGTools/SGTools/exceptions.h new file mode 100644 index 0000000000000000000000000000000000000000..2de48a5cab1753d3793d107addd977c2d71a3eb2 --- /dev/null +++ b/Control/SGTools/SGTools/exceptions.h @@ -0,0 +1,97 @@ +// This file's extension implies that it's C, but it's really -*- C++ -*-. + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// $Id$ +/** + * @file SGTools/exceptions.h + * @author scott snyder <snyder@bnl.gov> + * @date Nov, 2013 + * @brief Exceptions that can be thrown by SGTools. + */ + + +#ifndef SGTOOLS_EXCEPTIONS_H +#define SGTOOLS_EXCEPTIONS_H + + +#include "GaudiKernel/ClassID.h" +#include <typeinfo> +#include <stdexcept> +#include <string> + + +namespace SG { + + +/** + * @brief Exception --- Bad cast of DataProxy with CLID + * + * You tried to retrieve an object in StoreGate as an incompatible type. + */ +class ExcBadDataProxyCast + : public std::bad_cast +{ +public: + /** + * @brief Constructor. + * @param id CLID of the DataProxy. + * @param tid Type to which we're trying to convert the object. + */ + ExcBadDataProxyCast (CLID id, const std::type_info& tid); + + + // Needed for c++98 compatibility. + ~ExcBadDataProxyCast() throw() {} + + + /** + * @brief Return the message for this exception. + */ + virtual const char* what() const throw(); + + +private: + /// The message for this exception. + std::string m_what; +}; + + +/** + * @brief Throw an ExcBadDataProxyCast exception. + * @param id CLID of the DataProxy. + * @param tid Type to which we're trying to convert the object. + */ +void throwExcBadDataProxyCast (CLID id, const std::type_info& tid); + + +/** + * @brief Exception --- Proxy collision for clid/key + * + * DataStore was attempting to fill in the CLID/key for a dummy proxy, + * but there was already another proxy present with that CLID/key. + * + * This should never happen. + */ +class ExcProxyCollision + : public std::runtime_error +{ +public: + /** + * @brief Constructor. + * @param id CLID we're trying to set on the dummy proxy. + * @param key Key we're trying to set on the dummy proxy. + * @param primary_id CLID of the existing proxy. + * @param primary_key Key of the existing proxy. + */ + ExcProxyCollision (CLID id, const std::string& key, + CLID primary_id, const std::string& primary_key); +}; + + +} // namespace SG + + +#endif // not SGTOOLS_EXCEPTIONS_H diff --git a/Control/SGTools/SGTools/hashtable.h b/Control/SGTools/SGTools/hashtable.h new file mode 100755 index 0000000000000000000000000000000000000000..42d0e2989fc6026bd051e3f5d00ea6eb9f677466 --- /dev/null +++ b/Control/SGTools/SGTools/hashtable.h @@ -0,0 +1,17 @@ +// This file's extension implies that it's C, but it's really -*- C++ -*-. + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// $Id: hashtable.h,v 1.2 2008-09-17 01:17:05 binet Exp $ + +#ifndef SGTOOLS_HASHTABLE_H +#define SGTOOLS_HASHTABLE_H 1 + +#ifndef CXXUTILS_HASHTABLE_H + #include "CxxUtils/hashtable.h" +#endif + +#endif /* !SGTOOLS_HASHTABLE_H */ + diff --git a/Control/SGTools/SGTools/ptrhash.h b/Control/SGTools/SGTools/ptrhash.h new file mode 100644 index 0000000000000000000000000000000000000000..b807abbaf06e13aaad7fa9ad315005d16d6568fd --- /dev/null +++ b/Control/SGTools/SGTools/ptrhash.h @@ -0,0 +1,50 @@ +// This file's extension implies that it's C, but it's really -*- C++ -*-. + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// $Id: ptrhash.h,v 1.1 2008-04-08 16:05:32 ssnyder Exp $ +/** + * @file SGTools/ptrhash.h + * @author scott snyder <snyder@bnl.gov> + * @date Mon, 2008 + * @brief Improved hash function for pointers. + */ + + +#ifndef SGTOOLS_PTRHASH_H +#define SGTOOLS_PTRHASH_H + + +namespace SG { + + +/** + * @brief Improved hash function for pointers. + * + * The default hash function for pointers used by @c unordered_map and friends + * is just the result of casting the pointer to an int. + * The problem is that most pointers one deals with are going + * to be aligned; if the pointers are to objects obtained through malloc, + * then on all systems we deal with, at least the lower three bits + * of the pointer will always be clear. Since @c unordered_map + * uses a bucket-hash scheme, this means that only 1/8 of the buckets + * will be used in such a case, resulting in lower efficiency. + * + * Here, we try to avoid this problem. + */ +struct ptrhash +{ + std::size_t operator() (const void* p) const + { + std::size_t x = reinterpret_cast<std::size_t> (p); + return (x>>3) ^ (x&7); + } +}; + + +} // namespace SG + + +#endif // not SGTOOLS_PTRHASH_H diff --git a/Control/SGTools/SGTools/safe_clid.h b/Control/SGTools/SGTools/safe_clid.h new file mode 100755 index 0000000000000000000000000000000000000000..ff48a1d7a33cef896e4b53557db3f816ad7b16f0 --- /dev/null +++ b/Control/SGTools/SGTools/safe_clid.h @@ -0,0 +1,58 @@ +// This file's extension implies that it's C, but it's really -*- C++ -*-. + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// $Id: safe_clid.h,v 1.2 2005-11-08 22:01:30 ssnyder Exp $ + +/** + * @file SGTools/safe_clid.h + * @author scott snyder + * @date Nov 2005 + * @brief Find the class ID of a type, without triggering an error + * if it isn't defined. + * + * The general interface for finding the class ID for some type @a T + * is to use @a ClassID_traits<T>::ID(). However, if no class ID + * has been defined for @a T, this will result in a compilation error. + * In some cases, where the class ID can be considered optional, this + * can severely restrict the applicability of generic code. + * + * This header provides @a SG::safe_clid<T>(), which should return + * the class ID of @T, or @a CLID_NULL if @a T does not have a defined + * class ID (without causing an error). + * + * The implementation relies on the fact that when the class ID traits + * class gets specialized for a specific class ID, it defines + * @a has_classID_tag. The @a CLASS_DEF macro makes this definition, + * but if you specialize @a ClassID_traits yourself, you must remember + * to include @a has_classID_tag, or this function won't work. + */ + +#ifndef SGTOOLS_SAFECLID_H +#define SGTOOLS_SAFECLID_H + + +#include "GaudiKernel/ClassID.h" + + +namespace SG { + + +/** + * @brief Return the class ID of @a T, or @a CLID_NULL if it doesn't + * have one. Avoids compilation errors if the class ID + * is not defined. + */ +template <class T> +CLID safe_clid(); + + +} // namespace SG + + +#include "SGTools/safe_clid.icc" + + +#endif // not SGTOOLS_SAFECLID_H diff --git a/Control/SGTools/SGTools/safe_clid.icc b/Control/SGTools/SGTools/safe_clid.icc new file mode 100755 index 0000000000000000000000000000000000000000..8645a886bfac7f33dd47eb5f9b103f6f79290a4d --- /dev/null +++ b/Control/SGTools/SGTools/safe_clid.icc @@ -0,0 +1,121 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// $Id: safe_clid.icc,v 1.2 2007-12-14 03:12:34 binet Exp $ +/** + * @file SGTools/safe_clid.icc + * @author scott snyder + * @date Nov 2005 + * @brief Find the class ID of a type, without triggering an error + * if it isn't defined. + * Implementation file. + */ + +#include "SGTools/ClassID_traits.h" +#include "AthenaKernel/tools/type_tools.h" +#include "boost/type_traits/remove_pointer.hpp" + + +namespace SG { + + +//------------------------------------------------------------------------- +// Here's the first part. @a safe_clid has the job of calling one of the +// two @a safe_clid_1 overrides, depending on the state of the traits +// class @a has_classID_tag definition. We want the first one to be called +// when @a has_classID_tag is @a true_tag, and the second to be called +// in other cases (including the possibility that the typedef does not exist). +// There are three possibilities to consider. +// +// 1. The traits class defines @a has_classID_tag as @a true_tag. +// Here, both decl 1 and 2 match the call. It turns out +// that we can't use partial ordering to discriminate between +// these two on the basis of the tag (second) argument alone. +// That's the purpose of the first (dummy) argument. By making +// it a pointer in decl 1 and completely generic in decl 2, +// we ensure that decl 1 is a more specific match when both +// decls are allowed. +// +// 2. The traits class defines @a has_classID_tag as something +// other than @a true_tag. In this case, decl 1 doesn't match +// the call, but decl 2 will. So decl 2 will be called. +// +// 3. The traits class has no definition for @a has_classID_tag. +// In this case, the type named in decl 1 does not exist. +// However, that is @e not an error --- it just means that +// decl 1 won't be considered as a candidate overload. +// (Look up ``substitution failure is not an error'' (SFINAE).) +// So again, decl 2 gets called. Note that the requirement +// to handle this case (which comes about because the unspecialized +// version of @a ClassID_traits does not define this typedef) +// is why this may look backwards, using @a true_tag in the call, +// and the traits class typedef in the argument. + + +// Decl 1 +template <class T> +CLID safe_clid_1 (T*, typename ClassID_traits<T>::has_classID_tag); + +// Decl 2 +template <class T, class U> +CLID safe_clid_1 (T, U); + +// This is the public entry point. +template <class T> +CLID safe_clid() +{ + return safe_clid_1 ((T*)0, type_tools::true_tag()); +} + + +//------------------------------------------------------------------------- +// Here is the definition for decl 1. This gets called when the +// traits class defines @a has_classID_tag as @a true_tag. +// So we can go ahead and ask for the ID in this case. + +template <class T> +CLID safe_clid_1 (T*, typename ClassID_traits<T>::has_classID_tag) +{ + return ClassID_traits<T>::ID(); +} + + +//------------------------------------------------------------------------- +// Here is the definition for decl 2. This gets called when the traits +// class does not define @a has_classID_tag is @a true_tag. +// But there is one further decision to be made. If @a T derives +// from @a DataObject, then we can still get the class ID. +// Otherwise, we must return @a CLID_NULL. + +// This is called if @a T does not derive from @a DataObject. +// Return @a CLID_NULL. +template <class T, bool B> +struct safe_clid_2 +{ + static CLID clid() { return CLID_NULL; } +}; + +// This specialization is used if @a T does derive from @a DataObject. +// This returns the class ID. +template <class T> +struct safe_clid_2<T, true> +{ + static CLID clid() { return ClassID_traits<T>::ID(); } +}; + +// This is the definition corresponding to decl 2 above. +// We test @a s_isDataObject in the traits class. +// Note that here @a T will be a pointer to the class we're +// actually interested in, so we need to strip a pointer. +template <class T, class U> +CLID safe_clid_1 (T, U) +{ + typedef typename boost::remove_pointer<T>::type typ; + return safe_clid_2<typ, ClassID_traits<typ>::s_isDataObject>::clid(); +} + + +} // namespace SG + + diff --git a/Control/SGTools/SGTools/selection.xml b/Control/SGTools/SGTools/selection.xml new file mode 100755 index 0000000000000000000000000000000000000000..8cad941dc6b490e4917dd3df7bf62b3797d7754e --- /dev/null +++ b/Control/SGTools/SGTools/selection.xml @@ -0,0 +1,12 @@ +<lcgdict> + <class name="IProxyDictWithPool" /> + <class name="IStringPool" /> + <class name="DataBucketBase" /> + <class name="SG::DataProxy" /> + <exclusion> + <class pattern="*iterator*tuple*long*unsigned*int*"/> + </exclusion> + <class name="std::vector<SG::DataProxy*>" /> + <class name="std::vector<const SG::DataProxy*>" /> + <class name="SG::BaseInfoBase" /> +</lcgdict> diff --git a/Control/SGTools/SGTools/unordered_map.h b/Control/SGTools/SGTools/unordered_map.h new file mode 100755 index 0000000000000000000000000000000000000000..8478446f5cd8d6b20d64dbd71dd2eea653fda4c1 --- /dev/null +++ b/Control/SGTools/SGTools/unordered_map.h @@ -0,0 +1,15 @@ +// This file's extension implies that it's C, but it's really -*- C++ -*-. + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// $Id: unordered_map.h,v 1.2 2008-09-17 01:17:05 binet Exp $ +#ifndef SGTOOLS_UNORDERED_MAP_H +#define SGTOOLS_UNORDERED_MAP_H 1 + +#ifndef CXXUTILS_UNORDERED_MAP_H + #include "CxxUtils/unordered_map.h" +#endif + +#endif /* !SGTOOLS_UNORDERED_MAP_H */ diff --git a/Control/SGTools/cmt/requirements b/Control/SGTools/cmt/requirements new file mode 100755 index 0000000000000000000000000000000000000000..782b742d6706d5a239135b62b1799e7ab86d36f1 --- /dev/null +++ b/Control/SGTools/cmt/requirements @@ -0,0 +1,44 @@ +package SGTools +author Paolo Calafiura <Paolo.Calafiura@cern.ch> +author Srini Rajagopalan <srinir@bnl.gov> + +use AtlasPolicy AtlasPolicy-* + +use CxxUtils CxxUtils-* Control +use AthenaKernel AthenaKernel-* Control + +#need IAddressProvider.h, IResetable.h + +use AtlasBoost AtlasBoost-* External +use GaudiInterface GaudiInterface-* External + +library SGTools *.cxx +apply_pattern installed_library + +private +# Get the boost threads dso linked. +macro_append Boost_linkopts $(Boost_linkopts_thread) +macro_append SGTools_shlibflags $(Boost_linkopts) + +use SGAudCore SGAudCore-* Control/SGMon +use TestTools TestTools-* AtlasTest +use AtlasReflex AtlasReflex-* External -no_auto_imports + +apply_pattern lcgdict dict=SGTools selectionfile=selection.xml headerfiles="-s=${SGTools_root}/SGTools SGToolsDict.h" + +apply_pattern UnitTest_run unit_test=CLIDRegistry +apply_pattern UnitTest_run unit_test=VersionedKey +apply_pattern UnitTest_run unit_test=DataBucket \ + extrapatterns="^HistogramPersis.* INFO" +apply_pattern UnitTest_run unit_test=BaseInfo +apply_pattern UnitTest_run unit_test=safe_clid +apply_pattern UnitTest_run unit_test=crc64 +apply_pattern UnitTest_run unit_test=exceptions +apply_pattern UnitTest_run unit_test=StringPool +apply_pattern UnitTest_run unit_test=ClassName +apply_pattern UnitTest_run unit_test=DataProxy +apply_pattern UnitTest_run unit_test=DataStore +apply_pattern UnitTest_run unit_test=TransientAddress + +macro_append DOXYGEN_INPUT " ../doc" +end_private diff --git a/Control/SGTools/doc/MainPage.h b/Control/SGTools/doc/MainPage.h new file mode 100755 index 0000000000000000000000000000000000000000..6e9bb51c0e925b83b5df61ee0c3fc277ac2a868b --- /dev/null +++ b/Control/SGTools/doc/MainPage.h @@ -0,0 +1,29 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/** + +@mainpage + +This package contains implementation classes for StoreGate. + +@section uses Packages used + +@htmlinclude used_packages.html + +@section requirements requirements + +@include requirements + +@section refs More Documentation + +More information is available from the Athena wiki +<https://twiki.cern.ch/twiki/bin/view/Atlas/StoreGate> + +The code can be browsed using LXR +(http://alxr.usatlas.bnl.gov/lxr/source/atlas/Control/SGTools/) + + +@author Paolo Calafiura <Paolo.Calafiura@cern.ch> +*/ diff --git a/Control/SGTools/ispellwords b/Control/SGTools/ispellwords new file mode 100644 index 0000000000000000000000000000000000000000..a82d919b9c09d0ce345ab9e235e0750275080618 --- /dev/null +++ b/Control/SGTools/ispellwords @@ -0,0 +1,527 @@ +personal_ws-1.1 en 342 +updateItemList +decls +addSymLink +clid +resetOnly +requestRelease +DataBucketCast +EventHeader +cmt +SGAudCore +theApp +CLIDSvc +MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGTVIRGATTSYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE +SGToolsDict +StoreGateSvc +SGTools +bool +bla +Bleah +blu +Vukotic +ProxyMap +proxymap +toObjectType +dbbObject +pSGAudSvc +LXR +StreamBuffer +asStorable +Leggett +CxxUtils +crc +NoBase +builtins +cxx +utils +addAlias +rawVersionKey +FCA +Calafiura +DataObjects +symlinks +symLinks +symlinked +symLinked +castTo +cassert +typeinfoName +speeded +IOA +addInit +addint +CLASSVERSION +malloc +DataList +initGaudi +endcode +AtlasBoost +hpp +StorableConversions +SGIFolder +SGFolder +pDObj +MyDataObj +getMessageSvc +printf +gcc +getAddress +IProxyDictWithPool +pRange +Quarrie +DataModel +symlink +DataHandles +ctor +gaudi +cout +gdo +typedef'd +pObj +MyKey +BaseInfoBase +substr +mem +ajsdla +StorageType +TransientAddress +NN +Nuno +accessData +msg +ns +pok +TestTools +poly +unsetInput +regbase +retrieveAllVersions +pre +StatusCode +dbb +modifs +DataHeaderElement +SG +sg +circ +DF +timespec +setAlias +DHE +rhs +ClassID +classID +wrt +ItemList +CLIDs +CLID's +clids +refcount +refCount +Xed +xd +AbstractDataObj +dp +dep +createObj +InputDataHeader +dtor +TrEMBL +Gemmeren +AbstractType +BaseInfoBaseImpl +setDefaults +lkjasd +lkajsd +VK +vkey +wiki +AthenaKernel +persistency +AddressProvider +typeinfo +paks +mutex +StringPool +CLIDComps +MacOSX +outputLevel +typeName +copyVK +pMap +pmap +IStringPool +VersionedKey +CallBackID +behaviour +metafunction +pointee +setClid +converterTo +IConversionSvc +stdout +stringToKey +DataBucket +DataSvc +param +stateFlag +const +vtable +IOVSvc +hashtable +AtlasReflex +svcLocator +SGVersionedKey +templated +isInput +dobjs +fromStorable +DBDataModel +ptr +DataObj +SFINAE +dobj +DataBucketTraitFwd +genreflex +DataBucketBase +StlVectorClids +registerKey +MessageSvc +relPool +ClassName +Binet +binet +castObject +BuiltinsClids +sgkey +ProxyProvider +InterfaceID +INITIALCRC +SLC +GaudiKernel +DEFS +scott +CLASSDEF +DataHeader +cptr +getPrimaryClassID +clearStore +everything's +snyder +ssnyder +decl +doxygen +SGComps +aspdk +CLIDREG +castfnTo +outObject +dquarrie +DataStore +FIXME +forceRemove +dict +src +tinfo +DLT +demangled +refcounting +valgrind +Stl +DEFAULTKEY +refcounts +str +MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGDVIRGATTHYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE +clearAddress +DATAVECTOR +DataVector +StatusCodeSvc +SWISSPROT +CLIDRegistry +namespace +aliasKey +typeid +Schaffer +schaffer +inlined +chkconfig +DataBucketTrait +tryELRemap +tdef +Storable +storable +Rajagopalan +impl +castfn +CreateSvc +IPageAccessControlSvc +toType +INLINE +func +SGAudSvc +IOpaqueAddress +objName +ISGAudSvc +EventSelectorAthenaPool +html +baseinfo +BaseInfo +IProxyRegistry +icc +arg +eg +i'll +ULL +noAudSvc +pObject +API +FdB +IID +atoi +irt +ElementLink +resetFlag +MAXCLID +pgref +vkeys +addEntry +BaseInfoImpl +readback +keyToString +MINCLID +strlen +eval +indep +converterToHelper +StoreGate +struct +iostream +ints +versionKey +StoreMap +pMember +BaseType +IRegisterTransient +Versioned +mixup +ClassIDSvc +IMessageSvcHolder +SAFECLID +ECMA +SGFolderItem +retrieveHighestVersion +Ilija +args +IRegistry +initlist +removeProxy +enum +GaudiDataObj +uint +init +DataProxy +inObject +consultProvider +isDataObject +libSGTools +IProxyDict +ptrhash +htmlinclude +setProperty +IDC +DataObject +mainpage +calaf +CGL +asd +StorableConversion +pRegister +STLMAPCLIDS +StlMapClids +addr +laskjkd +t2pmap +T2pMap +typedef +instantiation +doesn +v1r19 +v19 +v16 +crc64addint +gcc4 +lookup +casted +SLC4 +typedefs +t2pRegister +t2p +ispellwords +addToStore +IResetable +runtime +RegisterAddBaseInit +keyless +Kittelmann +reinit +setTransientAddress +errNo +errno +checkreq +d3pds +defaultkey +isConst +bools +DataHandleBase +DataHandle +resized +ulonglong +ulong +ushort +uint8 +vec +savannah +cacheable +updateAddress +isValid +storeID +gcc43 +coverity +SGImplSvc +Paolo +wscript +Sebastien +sz +dst +MyType +MyCopyConversion +Base3 +Base2 +Base1 +instantiations +B3 +B2 +B1 +BASES3 +BASES2 +BASES1 +isn +Destructor +CopyConversionBase +cnv +initializations +initializer +recurse +AddBaseInfo +ourself +ARG2 +ARG1 +DEF2 +accessors +0x +decrement +fwk +itr1 +ok +T2PMap +EL +02u +ost +aren +CRC64 +unordered +unspecialized +HistogramPersis +DynamicType +dataPointer +typeless +itrEnd +itr +GaudiObject +resettable +nmatch +crc64 +0xd800000000000000ULL +POLY64REV +0x0000000000000000ULL +08X +test1 +test2 +fooB +MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGTVIRGATTSYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE +MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGDVIRGATTHYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE +MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGTVIRGATTSYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE +C874767DA8254746 +MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGDVIRGATTHYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE +2DF1AA17420FCA3F +NoAuxStore +AuxStore +CLASSAUXSTORE +MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGTVIRGATTSYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE +MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGDVIRGATTHYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE +MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGTVIRGATTSYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE +MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGDVIRGATTHYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE +dicts +AthContainers +AthContainersInterfaces +leggett +charles +setSGKey +setID +MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGTVIRGATTSYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE +MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGDVIRGATTHYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE +pTAd +addRef +key2 +key3 +key4 +MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGTVIRGATTSYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE +MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGDVIRGATTHYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE +setStore +clID +tAddr +ims +gLog +MsgStream +endreq +queryInterface +pTransient +proxy1 +proxy2 +proxy3 +exact1 +keyToString1 +keyToString2 +MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGTVIRGATTSYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE +MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGDVIRGATTHYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE +MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGTVIRGATTSYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE +MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGDVIRGATTHYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE +MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGTVIRGATTSYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE +MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGDVIRGATTHYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE +MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGTVIRGATTSYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE +MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGDVIRGATTHYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE +ExcBadDataProxyCast +keyMap +storeMap +tid +dummied +shouldn +ExcProxyCollision +dp1 +dp2 +dp1a +dp1b +dpx +dp3 +typeCount +tRange +proxyList +dp4 +dp1x +pac +MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGTVIRGATTSYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE +MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGDVIRGATTHYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE +MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGTVIRGATTSYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE +MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGDVIRGATTHYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE +abc diff --git a/Control/SGTools/share/BaseInfo_test.ref b/Control/SGTools/share/BaseInfo_test.ref new file mode 100755 index 0000000000000000000000000000000000000000..bae42c55f9e0a4e297a4d197d8aadfe147ef269b --- /dev/null +++ b/Control/SGTools/share/BaseInfo_test.ref @@ -0,0 +1,2 @@ +test1 +test2 diff --git a/Control/SGTools/share/CLIDRegistry_test.ref b/Control/SGTools/share/CLIDRegistry_test.ref new file mode 100755 index 0000000000000000000000000000000000000000..b5d0b6a45586b001a89587f8568a2ad420c975ae --- /dev/null +++ b/Control/SGTools/share/CLIDRegistry_test.ref @@ -0,0 +1,2 @@ +*** CLIDRegistry_test starts *** +*** CLIDRegistry_test OK *** diff --git a/Control/SGTools/share/ClassName_test.ref b/Control/SGTools/share/ClassName_test.ref new file mode 100755 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Control/SGTools/share/DataBucket_test.ref b/Control/SGTools/share/DataBucket_test.ref new file mode 100755 index 0000000000000000000000000000000000000000..1c572a185bb194cc452b59a4a31fe306ec409251 --- /dev/null +++ b/Control/SGTools/share/DataBucket_test.ref @@ -0,0 +1,48 @@ +ApplicationMgr SUCCESS +==================================================================================================================================== + Welcome to ApplicationMgr (GaudiCoreSvc v999r999) + running on karma on Thu Apr 17 17:22:20 2014 +==================================================================================================================================== +ApplicationMgr INFO Application Manager Configured successfully +EventLoopMgr WARNING Unable to locate service "EventSelector" +EventLoopMgr WARNING No events will be processed from external input. +HistogramPersis...WARNING Histograms saving not required. +ApplicationMgr INFO Application Manager Initialized successfully +ApplicationMgr Ready +int has_classID 244260744 version 1 and does not inherit from DataObject +const int* has_classID 244260744 +vector<int> has_classID 22592129 +GaudiDataObj has_classID 8010 and does inherit from DataObject +MyDataObj has_classID 8000 and does not inherit from DataObject +AbstractDataObj has_classID 8011 +AbstractType has_classID 8004 +Now we expect to see an error message: +----Error Message Starts--->> +SG::fromStorable WARNING can't convert stored DataObject 0x1c33120 to type (WrongType) + Unless you are following a symlink, it probably means you have a duplicate CLID = 8000 +<<---Error Message Ends------- +Now we expect to see an error message: +----Error Message Starts--->> +SG::fromStorable WARNING can't convert stored DataObject 0x1c33120 to type (WrongType) + Unless you are following a symlink, it probably means you have a duplicate CLID = 8000 +<<---Error Message Ends------- +Now we expect to see an error message: +----Error Message Starts--->> +SG::fromStorable WARNING null input pointer +<<---Error Message Ends------- +Now we expect to see an error message: +----Error Message Starts--->> +SG::fromStorable WARNING can't convert stored DataObject 0x1c33120 to type (WrongType) + Unless you are following a symlink, it probably means you have a duplicate CLID = 8010 +<<---Error Message Ends------- +Now we expect to see an error message: +----Error Message Starts--->> +SG::fromStorable WARNING can't convert stored DataObject 0x1e61c00 to type (WrongType) + Unless you are following a symlink, it probably means you have a duplicate CLID = 8010 +<<---Error Message Ends------- +test2 +SG::fromStorable WARNING can't convert stored DataObject 0x1c33120 to type (X3) + Unless you are following a symlink, it probably means you have a duplicate CLID = 8011 +test3 +lock +*** DataBucket_test OK *** diff --git a/Control/SGTools/share/DataProxy_test.ref b/Control/SGTools/share/DataProxy_test.ref new file mode 100644 index 0000000000000000000000000000000000000000..6a50354f32c714982bf1734756bcfe5b8f21d32a --- /dev/null +++ b/Control/SGTools/share/DataProxy_test.ref @@ -0,0 +1,4 @@ +test1 +test2 +lock +lock diff --git a/Control/SGTools/share/DataStore_test.ref b/Control/SGTools/share/DataStore_test.ref new file mode 100644 index 0000000000000000000000000000000000000000..6c942137c7273360a9dc36c067f4c3d08485b93b --- /dev/null +++ b/Control/SGTools/share/DataStore_test.ref @@ -0,0 +1,15 @@ +test_ctor +test_addToStore +test_addAlias +test_addSymLink +test_proxy_exact +test_proxy +test_typeCount +test_tRange +test_pRange +test_proxyList +test_keys +test_removeProxy +test_clearStore +test_t2p +test_dummy diff --git a/Control/SGTools/share/StringPool_test.ref b/Control/SGTools/share/StringPool_test.ref new file mode 100755 index 0000000000000000000000000000000000000000..94db96eba5c6144cacb615a17106269685c6e21a --- /dev/null +++ b/Control/SGTools/share/StringPool_test.ref @@ -0,0 +1,13 @@ +000000003FFFFFFF +000000000FD9252C MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGTVIRGATTSYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE +000000000EE07ECA MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGDVIRGATTHYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE +000000000AC0B3E3 ajsdla lkjasd lkjasd +000000003979421C paks aspdk pok asd +000000001B269909 asd laskjkd lkajsd +pool dump + 3fffffff 0 + ac0b3e3 3 ajsdla lkjasd lkjasd + ee07eca 2 MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGDVIRGATTHYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE + 3979421c 4 paks aspdk pok asd + fd9252c 1 MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGTVIRGATTSYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE + 1b269909 5 asd laskjkd lkajsd diff --git a/Control/SGTools/share/TransientAddress_test.ref b/Control/SGTools/share/TransientAddress_test.ref new file mode 100644 index 0000000000000000000000000000000000000000..204dae5613b633357b85b6b559c02a5aa7ff836d --- /dev/null +++ b/Control/SGTools/share/TransientAddress_test.ref @@ -0,0 +1,7 @@ +test1 +addRef 1 1 +addRef 2 1 +release 1 0 +release 2 0 +addRef 2 1 +release 2 0 diff --git a/Control/SGTools/share/VersionedKey_test.ref b/Control/SGTools/share/VersionedKey_test.ref new file mode 100644 index 0000000000000000000000000000000000000000..dcbda6f6b4c0a07fbf23caa99f409a16abfa40a7 --- /dev/null +++ b/Control/SGTools/share/VersionedKey_test.ref @@ -0,0 +1,3 @@ +Versioned Key 1=;01;bla +Versioned Key 2=;99;Bleah +Versioned Key 3=;00;default diff --git a/Control/SGTools/share/crc64_test.ref b/Control/SGTools/share/crc64_test.ref new file mode 100755 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Control/SGTools/share/exceptions_test.ref b/Control/SGTools/share/exceptions_test.ref new file mode 100644 index 0000000000000000000000000000000000000000..d3ec4082a460e8ae3e296c744065e41f35936c83 --- /dev/null +++ b/Control/SGTools/share/exceptions_test.ref @@ -0,0 +1,3 @@ +test1 +Bad cast of DataProxy with CLID 123 to type int +ExcProxyCollision: proxy collision for clid/key 123 / abc (primary 456 / def). diff --git a/Control/SGTools/share/safe_clid_test.ref b/Control/SGTools/share/safe_clid_test.ref new file mode 100755 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Control/SGTools/src/BaseInfo.cxx b/Control/SGTools/src/BaseInfo.cxx new file mode 100755 index 0000000000000000000000000000000000000000..f298359fd11da68be75fdbaa749bddfb02f972f6 --- /dev/null +++ b/Control/SGTools/src/BaseInfo.cxx @@ -0,0 +1,695 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// $Id: BaseInfo.cxx,v 1.9 2008-11-25 21:45:04 ssnyder Exp $ +/** + * @file SGTools/BaseInfo.cxx + * @author scott snyder + * @date Nov 2005 + * @brief Provide an interface for finding inheritance information + * at run time. + * Out-of-line implementation. + */ + +#include "SGTools/BaseInfo.h" +//#include "boost/thread/mutex.hpp" +#include <map> + + +namespace SG { + + +struct BaseInfoBaseImpl { + /// Structure to hold information about one base. + struct info { + /// Constructor. @a converter* and @a is_virtual are as for @a add_info. + info (BaseInfoBase::castfn_t* converter = 0, + BaseInfoBase::castfn_t* converterTo = 0, + bool is_virtual = false); + + /// Converter function. Takes a @a T* and converts to a pointer + /// to this base. + BaseInfoBase::castfn_t* m_converter; + + /// Converter function. Takes a pointer to this base and converts + /// to @a T*. + /// to this base. + BaseInfoBase::castfn_t* m_converterTo; + + /// True if the derivation from this base to @a T is via + /// virtual derivation. + bool m_is_virtual; + }; + + + /// CLID of this class. + CLID m_clid; + + /// Set to true when first created. + /// Reset after we scan for init functions. + bool m_needs_init; + + /// @c std::type_info of this class. + const std::type_info* m_typeinfo; + + + /// Hold base information indexed by class ID. + typedef std::map<CLID, info> clid_map_type; + clid_map_type m_clidmap; + + /// Hold base information indexed by @a type_info. + typedef std::map<const std::type_info*, info> ti_map_type; + ti_map_type m_timap; + + + /// Map of all CLIDs to @c BaseInfoBase instances. + typedef std::map<CLID, BaseInfoBase*> bi_by_clid_map_type; + static bi_by_clid_map_type* s_bi_by_clid; + + /// Map of all @c type_info names to @c BaseInfoBase instances. + typedef std::map<const std::type_info*, BaseInfoBase*> bi_by_ti_map_type; + static bi_by_ti_map_type* s_bi_by_ti; + + + /// Hold copy conversion information indexed by class ID. + typedef std::map<CLID, const CopyConversionBase*> clid_copyconversion_type; + clid_copyconversion_type m_clid_copyconversion_map; + + /// Hold copy conversion information indexed by @ type_info. + typedef std::map<const std::type_info*, const CopyConversionBase*> + ti_copyconversion_type; + ti_copyconversion_type m_ti_copyconversion_map; + + /// Holds @c BaseInfo classes awaiting initialization. + /// This is used to defer initialization until everything's loaded. + struct init_elem_t { + CLID m_clid; + const std::type_info* m_ti; + BaseInfoBase::init_func_t* m_init_func; + }; + static std::vector<init_elem_t>* s_init_list; + + + // To make sure that the maps get deleted at program termination. + struct Deleter { + ~Deleter(); + }; + static Deleter s_deleter; + + /// For thread-safety. + //static boost::mutex s_mutex; +}; + + + +/** + * @brief Return the CLID for this class. + */ +CLID BaseInfoBase::clid() const +{ + return m_impl->m_clid; +} + + +/** + * @brief Return the @c std::type_info for this class. + */ +const std::type_info& BaseInfoBase::typeinfo() const +{ + return *m_impl->m_typeinfo; +} + + +/** + * @brief Cast to a base pointer. + * @param p The pointer to cast (a @a T* cast to a @a void*). + * @param clid ID of the class to which to cast. + * @return The pointer cast to the requested type, returned + * as a @a void*. @a clid must be known to be a base + * of @a T; otherwise, 0 will be returned. + */ +void* BaseInfoBase::cast (void* p, CLID clid) const +{ + const BaseInfoBaseImpl::clid_map_type& map = m_impl->m_clidmap; + BaseInfoBaseImpl::clid_map_type::const_iterator i = map.find (clid); + if (i != map.end()) + return i->second.m_converter (p); + return 0; +} + + +/** + * @brief Cast to a base pointer. + * @param p The pointer to cast (a @a T* cast to a @a void*). + * @param clid @a type_info of the class to which to cast. + * @return The pointer cast to the requested type, returned + * as a @a void*. @a tinfo must be known to be a base + * of @a T; otherwise, 0 will be returned. + */ +void* BaseInfoBase::cast (void* p, const std::type_info& tinfo) const +{ + const BaseInfoBaseImpl::ti_map_type& map = m_impl->m_timap; + BaseInfoBaseImpl::ti_map_type::const_iterator i = map.find (&tinfo); + if (i != map.end()) + return i->second.m_converter (p); + return 0; +} + + +/** + * @brief Cast to a derived pointer. + * @param p The pointer to cast (a @a B* cast to a @a void*). + * @param clid ID of the class @a B from which to cast. + * @return The pointer cast to the requested type, returned + * as a @a void*. @a clid must be known to be a base + * of @a T; otherwise, 0 will be returned. + * 0 will also be returned if the @a dynamic_cast fails. + */ +void* BaseInfoBase::castTo (void* p, CLID clid) const +{ + const BaseInfoBaseImpl::clid_map_type& map = m_impl->m_clidmap; + BaseInfoBaseImpl::clid_map_type::const_iterator i = map.find (clid); + if (i != map.end() && i->second.m_converterTo) + return i->second.m_converterTo (p); + return 0; +} + + +/** + * @brief Cast to a derived pointer. + * @param p The pointer to cast (a @a B* cast to a @a void*). + * @param clid @a type_info of the class @a B from which to cast. + * @return The pointer cast to the requested type, returned + * as a @a void*. @a tinfo must be known to be a base + * of @a T; otherwise, 0 will be returned. + * 0 will also be returned if the @a dynamic_cast fails. + */ +void* BaseInfoBase::castTo (void* p, const std::type_info& tinfo) const +{ + const BaseInfoBaseImpl::ti_map_type& map = m_impl->m_timap; + BaseInfoBaseImpl::ti_map_type::const_iterator i = map.find (&tinfo); + if (i != map.end() && i->second.m_converterTo) + return i->second.m_converterTo (p); + return 0; +} + + +/** + * @brief Return a function for casting to a base pointer. + * @param clid ID of the class to which to cast. + * @return A function to convert a pointer to a @c T to a pointer + * to the type identified by @a clid. + * @a clid must be known to be a base + * of @a T; otherwise, 0 will be returned. + */ +BaseInfoBase::castfn_t* BaseInfoBase::castfn (CLID clid) const +{ + const BaseInfoBaseImpl::clid_map_type& map = m_impl->m_clidmap; + BaseInfoBaseImpl::clid_map_type::const_iterator i = map.find (clid); + if (i != map.end()) + return i->second.m_converter; + return 0; +} + + +/** + * @brief Return a function for casting to a base pointer. + * @param clid @a type_info of the class to which to cast. + * @return A function to convert a pointer to a @c T to a pointer + * to the type identified by @a tinfo. + * @a tinfo must be known to be a base + * of @a T; otherwise, 0 will be returned. + */ +BaseInfoBase::castfn_t* +BaseInfoBase::castfn (const std::type_info& tinfo) const +{ + const BaseInfoBaseImpl::ti_map_type& map = m_impl->m_timap; + BaseInfoBaseImpl::ti_map_type::const_iterator i = map.find (&tinfo); + if (i != map.end()) + return i->second.m_converter; + return 0; +} + + +/** + * @brief Return a function for casting to a derived pointer. + * @param clid ID of the class @a B from which to cast. + * @return A function to convert a pointer to a @a B to a pointer + * to a @a T. @a B must be known to be a base + * of @a T; otherwise, 0 will be returned. + * 0 will also be returned if the @a dynamic_cast fails. + */ +BaseInfoBase::castfn_t* BaseInfoBase::castfnTo (CLID clid) const +{ + const BaseInfoBaseImpl::clid_map_type& map = m_impl->m_clidmap; + BaseInfoBaseImpl::clid_map_type::const_iterator i = map.find (clid); + if (i != map.end()) + return i->second.m_converterTo; + return 0; +} + + +/** + * @brief Return a function for casting to a derived pointer. + * @param clid @a type_info of the class @a B from which to cast. + * @return A function to convert a pointer to a @a B to a pointer + * to a @a T. @a B must be known to be a base + * of @a T; otherwise, 0 will be returned. + * 0 will also be returned if the @a dynamic_cast fails. + */ +BaseInfoBase::castfn_t* +BaseInfoBase::castfnTo (const std::type_info& tinfo) const +{ + const BaseInfoBaseImpl::ti_map_type& map = m_impl->m_timap; + BaseInfoBaseImpl::ti_map_type::const_iterator i = map.find (&tinfo); + if (i != map.end()) + return i->second.m_converterTo; + return 0; +} + + +/** + * @brief Return the class IDs of all known bases of @a T (that + * have class IDs). The list will include @a T itself. + */ +std::vector<CLID> BaseInfoBase::get_bases() const +{ + const BaseInfoBaseImpl::clid_map_type& map = m_impl->m_clidmap; + std::vector<CLID> v; + v.reserve (map.size()); + for (BaseInfoBaseImpl::clid_map_type::const_iterator i = map.begin(); + i != map.end(); + ++i) + v.push_back (i->first); + return v; +} + + +/** + * @brief Return the @c type_info's of all known bases of @a T. + * The list will include @a T itself. + */ +std::vector<const std::type_info*> BaseInfoBase::get_ti_bases() const +{ + const BaseInfoBaseImpl::ti_map_type& map = m_impl->m_timap; + std::vector<const std::type_info*> v; + v.reserve (map.size()); + for (BaseInfoBaseImpl::ti_map_type::const_iterator i = map.begin(); + i != map.end(); + ++i) + v.push_back (i->first); + return v; +} + + +/** + * @brief Return true if @a clid is the ID of a class that + * is known to be a base of @a T. @a T is considered + * to be its own base for this purpose. + * @param clid The ID of the class to test. + */ +bool BaseInfoBase::is_base (CLID clid) const +{ + const BaseInfoBaseImpl::clid_map_type& map = m_impl->m_clidmap; + BaseInfoBaseImpl::clid_map_type::const_iterator i = map.find (clid); + return i != map.end(); +} + + +/** + * @brief Return true if @a tinfo is the @a type_info of a class that + * is known to be a base of @a T. @a T is considered + * to be its own base for this purpose. + * @param clid The ID of the class to test. + */ +bool BaseInfoBase::is_base (const std::type_info& tinfo) const +{ + const BaseInfoBaseImpl::ti_map_type& map = m_impl->m_timap; + BaseInfoBaseImpl::ti_map_type::const_iterator i = map.find (&tinfo); + return i != map.end(); +} + + +/** + * @brief Return true if @a clid is the ID of a class that + * is known to be a virtual base of @a T. (This will always + * be false for @a T itself.) + * @param clid The ID of the class to test. + */ +bool BaseInfoBase::is_virtual (CLID clid) const +{ + const BaseInfoBaseImpl::clid_map_type& map = m_impl->m_clidmap; + BaseInfoBaseImpl::clid_map_type::const_iterator i = map.find (clid); + if (i != map.end()) + return i->second.m_is_virtual; + return false; +} + + +/** + * @brief Return true if @a tinfo is the @a std::type_info of a class that + * is known to be a virtual base of @a T. (This will always + * be false for @a T itself.) + * @param tinfo The @a std::type_info of the class to test. + */ +bool BaseInfoBase::is_virtual (const std::type_info& tinfo) const +{ + const BaseInfoBaseImpl::ti_map_type& map = m_impl->m_timap; + BaseInfoBaseImpl::ti_map_type::const_iterator i = map.find (&tinfo); + if (i != map.end()) + return i->second.m_is_virtual; + return false; +} + + +/** + * @brief Search for a copy conversion to @c tinfo. + * @param tinfo The class to which we want to convert. + * + * Returns the conversion instance or 0. + */ +const CopyConversionBase* +BaseInfoBase::copy_conversion (const std::type_info& tinfo) const +{ + const BaseInfoBaseImpl::ti_copyconversion_type& map = + m_impl->m_ti_copyconversion_map; + BaseInfoBaseImpl::ti_copyconversion_type::const_iterator i = + map.find (&tinfo); + if (i != map.end()) + return i->second; + return 0; +} + + +/** + * @brief Search for a copy conversion to @c clid. + * @param clid The class to which we want to convert. + * + * Returns the conversion instance or 0. + */ +const CopyConversionBase* +BaseInfoBase::copy_conversion (CLID clid) const +{ + const BaseInfoBaseImpl::clid_copyconversion_type& map = + m_impl->m_clid_copyconversion_map; + BaseInfoBaseImpl::clid_copyconversion_type::const_iterator i = + map.find (clid); + if (i != map.end()) + return i->second; + return 0; +} + + +/** + * @brief Add a new copy conversion. + * @param clid The @c CLID of the target class. + * @param tinfo The @c std::type_info of the target class. + * @param cnv A @c CopyConversionBase instance describing the conversion. + * + * The @c BaseInfoBase takes ownership of the @c cnv object. + */ +void +BaseInfoBase::add_copy_conversion (CLID clid, + const std::type_info& tinfo, + const CopyConversionBase* cnv) +{ + if (clid != CLID_NULL) + m_impl->m_clid_copyconversion_map[clid] = cnv; + m_impl->m_ti_copyconversion_map[&tinfo] = cnv; +} + + +/** + * @brief Return known copy conversions. + * + * Returns the CLIDs of all target classes that have been registered + * with this one for copy conversion. + */ +std::vector<CLID> +BaseInfoBase::get_copy_conversions() const +{ + std::vector<CLID> out; + out.reserve (m_impl->m_clid_copyconversion_map.size()); + for (BaseInfoBaseImpl::clid_copyconversion_type::const_iterator it = + m_impl->m_clid_copyconversion_map.begin(); + it != m_impl->m_clid_copyconversion_map.end(); + ++it) + { + out.push_back (it->first); + } + return out; +} + + +/** + * @brief Add information about one base class. + * @param clid The class ID of the base. May be @a CLID_NULL if no + * class ID is available. + * @param tinfo The @a std::type_info of the base. + * @param converter Converter function. This should be able to + * convert a @a T* to a pointer to this base. + * @param converterTo Converter function. This should be able to + * convert a pointer to this base to a @a T*. + * @param is_virtual True if the derivation from this base to @a T + * is via virtual derivation. + */ +void BaseInfoBase::add_info (CLID clid, + const std::type_info& tinfo, + castfn_t* converter, + castfn_t* converterTo, + bool is_virtual) +{ + if (clid == CLID_NULL) + clid = clid_from_initlist (tinfo); + if (m_impl->m_timap.find (&tinfo) == m_impl->m_timap.end()) { + if (clid != CLID_NULL) + m_impl->m_clidmap[clid] = + BaseInfoBaseImpl::info (converter, converterTo, is_virtual); + m_impl->m_timap[&tinfo] = + BaseInfoBaseImpl::info (converter, converterTo, is_virtual); + } +} + + +/** + * @brief Convenience constructor. + * @param converter Converter function. This should be able to + * convert a @a T* to a pointer to this base. + * @param converterTo Converter function. This should be able to + * convert a pointer to this base to a @a T*. + * @param is_virtual True if the derivation from this base to @a T + * is via virtual derivation. + * + * The defaults are there just so this class can be used with STL + * containers that require a default ctor. + */ +BaseInfoBaseImpl::info::info (BaseInfoBase::castfn_t* converter /*= 0*/, + BaseInfoBase::castfn_t* converterTo /*= 0*/, + bool is_virtual /*= false*/) + : m_converter (converter), + m_converterTo (converterTo), + m_is_virtual (is_virtual) +{ +} + + +/** + * @brief Constructor. + * @param clid The class ID of this class. May be @c CLID_NULL if no + * ID is available. + * @param tinfo The @c std::type_info for this class. + */ +BaseInfoBase::BaseInfoBase (CLID clid, const std::type_info& tinfo) + : m_impl (new BaseInfoBaseImpl) +{ + if (clid == CLID_NULL) + clid = clid_from_initlist (tinfo); + m_impl->m_clid = clid; + m_impl->m_typeinfo = &tinfo; + m_impl->m_needs_init = true; + + //boost::mutex::scoped_lock lock (BaseInfoBaseImpl::s_mutex); + if (!BaseInfoBaseImpl::s_bi_by_clid) + BaseInfoBaseImpl::s_bi_by_clid = new BaseInfoBaseImpl::bi_by_clid_map_type; + if (!BaseInfoBaseImpl::s_bi_by_ti) + BaseInfoBaseImpl::s_bi_by_ti = new BaseInfoBaseImpl::bi_by_ti_map_type; + + // Register this instance in the static maps. + if (clid != CLID_NULL) + (*BaseInfoBaseImpl::s_bi_by_clid)[clid] = this; + (*BaseInfoBaseImpl::s_bi_by_ti)[&tinfo] = this; +} + + +/** + * @brief Destructor. + */ +BaseInfoBase::~BaseInfoBase() +{ + for (BaseInfoBaseImpl::ti_copyconversion_type::iterator it = + m_impl->m_ti_copyconversion_map.begin(); + it != m_impl->m_ti_copyconversion_map.end(); + ++it) + { + delete it->second; + } + delete m_impl; +} + + +/** + * @brief Find the @c BaseInfoBase instance for @c clid. + * @param clid The class ID of the class for which we want information. + * + * Returns 0 if no @c BaseInfoBase instance is available. + */ +const BaseInfoBase* BaseInfoBase::find (CLID clid) +{ + //boost::mutex::scoped_lock lock (BaseInfoBaseImpl::s_mutex); + if (!BaseInfoBaseImpl::s_bi_by_clid) return 0; + BaseInfoBaseImpl::bi_by_clid_map_type::iterator i = + BaseInfoBaseImpl::s_bi_by_clid->find (clid); + if (i != BaseInfoBaseImpl::s_bi_by_clid->end()) { + if (!i->second->m_impl->m_needs_init) + return i->second; + i->second->m_impl->m_needs_init = false; + } + + // Try the initlist. + if (BaseInfoBaseImpl::s_init_list) { + for (size_t j = 0; j < BaseInfoBaseImpl::s_init_list->size(); j++) { + if ((*BaseInfoBaseImpl::s_init_list)[j].m_clid == clid) { + BaseInfoBase::init_func_t* init = + (*BaseInfoBaseImpl::s_init_list)[j].m_init_func; + BaseInfoBaseImpl::s_init_list->erase + (BaseInfoBaseImpl::s_init_list->begin() + j); + --j; + init(); + i = BaseInfoBaseImpl::s_bi_by_clid->find (clid); + } + } + } + if (i != BaseInfoBaseImpl::s_bi_by_clid->end()) + return i->second; + + return 0; +} + + +/** + * @brief Find the @c BaseInfoBase instance for @c tinfo. + * @param tinfo The @c std::type_info of the class + * for which we want information. + * + * Returns 0 if no @c BaseInfoBase instance is available. + */ +const BaseInfoBase* BaseInfoBase::find (const std::type_info& tinfo) +{ + //boost::mutex::scoped_lock lock (BaseInfoBaseImpl::s_mutex); + if (!BaseInfoBaseImpl::s_bi_by_ti) return 0; + BaseInfoBaseImpl::bi_by_ti_map_type::iterator i = + BaseInfoBaseImpl::s_bi_by_ti->find (&tinfo); + if (i != BaseInfoBaseImpl::s_bi_by_ti->end()) { + if (!i->second->m_impl->m_needs_init) + return i->second; + i->second->m_impl->m_needs_init = false; + } + + // Try the initlist. + if (BaseInfoBaseImpl::s_init_list) { + for (size_t j = 0; j < BaseInfoBaseImpl::s_init_list->size(); j++) { + if ((*BaseInfoBaseImpl::s_init_list)[j].m_ti == &tinfo) { + BaseInfoBase::init_func_t* init = + (*BaseInfoBaseImpl::s_init_list)[j].m_init_func; + BaseInfoBaseImpl::s_init_list->erase + (BaseInfoBaseImpl::s_init_list->begin() + j); + --j; + init(); + i = BaseInfoBaseImpl::s_bi_by_ti->find (&tinfo); + } + } + } + if (i != BaseInfoBaseImpl::s_bi_by_ti->end()) + return i->second; + + return 0; +} + + +/** + * @brief Register an initialization function. + * @param clid The class ID of the class being registered. + * @param tinfo The @c std::type_info for the class being registered. + * @param init_func Function to initialize @c BaseInfo for the class. + */ +void BaseInfoBase::addInit (CLID clid, + const std::type_info* tinfo, + init_func_t* init_func) +{ + //boost::mutex::scoped_lock lock (BaseInfoBaseImpl::s_mutex); + if (!BaseInfoBaseImpl::s_init_list) + BaseInfoBaseImpl::s_init_list = + new std::vector<BaseInfoBaseImpl::init_elem_t>; + BaseInfoBaseImpl::init_elem_t elem; + elem.m_clid = clid; + elem.m_ti = tinfo; + elem.m_init_func = init_func; + BaseInfoBaseImpl::s_init_list->push_back (elem); + + if (BaseInfoBaseImpl::s_bi_by_ti) { + BaseInfoBaseImpl::bi_by_ti_map_type::iterator i = + BaseInfoBaseImpl::s_bi_by_ti->find (tinfo); + if (i != BaseInfoBaseImpl::s_bi_by_ti->end() && + !i->second->m_impl->m_needs_init) + i->second->m_impl->m_needs_init = true; + } +} + + +/** + * @brief Run initializations for this class, if needed. + */ +void BaseInfoBase::maybeInit() +{ + if (m_impl->m_needs_init) + find (*m_impl->m_typeinfo); +} + + + +/** + * @brief Try to translate a type_info to a CLID by looking in the initlist. + * @param tinfo The type to translate. + * @returns The corresponding CLID, or CLID_NULL. + */ +CLID BaseInfoBase::clid_from_initlist (const std::type_info& tinfo) +{ + if (!BaseInfoBaseImpl::s_init_list) return CLID_NULL; + size_t sz = BaseInfoBaseImpl::s_init_list->size(); + for (size_t i = 0; i < sz; i++) { + const BaseInfoBaseImpl::init_elem_t& elt = + (*BaseInfoBaseImpl::s_init_list)[i]; + if (elt.m_ti == &tinfo) + return elt.m_clid; + } + return CLID_NULL; +} + + +/// Declare the static members of @c BaseInfoBaseImpl. +BaseInfoBaseImpl::bi_by_clid_map_type* BaseInfoBaseImpl::s_bi_by_clid = 0; +BaseInfoBaseImpl::bi_by_ti_map_type* BaseInfoBaseImpl::s_bi_by_ti = 0; +std::vector<BaseInfoBaseImpl::init_elem_t>* BaseInfoBaseImpl::s_init_list = 0; +//boost::mutex BaseInfoBaseImpl::s_mutex; + +// To get them deleted. +BaseInfoBaseImpl::Deleter BaseInfoBaseImpl::s_deleter; +BaseInfoBaseImpl::Deleter::~Deleter() +{ + delete s_bi_by_clid; + delete s_bi_by_ti; + delete s_init_list; +} + +} // namespace SG diff --git a/Control/SGTools/src/CLIDRegistry.cxx b/Control/SGTools/src/CLIDRegistry.cxx new file mode 100755 index 0000000000000000000000000000000000000000..a21906f1e425e96ec55a2f8ab849b36ebabf6793 --- /dev/null +++ b/Control/SGTools/src/CLIDRegistry.cxx @@ -0,0 +1,60 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "SGTools/CLIDRegistry.h" +/* #include <algorithm> */ +using namespace std; + +const unsigned long CLIDRegistry::MINCLID = detail::MINCLID; +const unsigned long CLIDRegistry::MAXCLID = detail::MAXCLID; +unsigned int _alreadyDone (0); + + +// bool +// CLIDRegistry::addEntry(unsigned long id, const string& typeName) { +// assert( MINCLID <= id && id <= MAXCLID ); +// registry().push_back(pair<unsigned long, string>(id,typeName)); +// return true; +// } + + +CLIDRegistry::const_iterator CLIDRegistry::begin() { +#ifdef CLIDREG_DEBUG + cerr << "CLIDRegistry::begin: returns " + << &*(registry().begin()) << " for registry " <<®istry() + <<endl; +#endif + return registry().begin(); +} + + +CLIDRegistry::const_iterator CLIDRegistry::end() { +#ifdef CLIDREG_DEBUG + cerr << "CLIDRegistry::end: returns " + << &*(registry().end()) << " for registry " <<®istry() + <<endl; +#endif + return registry().end(); + //return unique(registry().begin(), registry().end()); //FIXME O(N)! +} + +bool +CLIDRegistry::hasNewEntries() { + return (_alreadyDone < CLIDRegistry::registry().size()); +} + +std::pair<CLIDRegistry::const_iterator, CLIDRegistry::const_iterator> +CLIDRegistry::newEntries() { + std::pair<CLIDRegistry::const_iterator, CLIDRegistry::const_iterator> ret = + std::make_pair(CLIDRegistry::begin()+_alreadyDone, + CLIDRegistry::end()); + _alreadyDone = CLIDRegistry::registry().size(); + return ret; +} + + +CLIDRegistry::CLIDRegistryImpl& CLIDRegistry::registry() { + static CLIDRegistryImpl _reg; + return _reg; +} diff --git a/Control/SGTools/src/DataHandleBase.cxx b/Control/SGTools/src/DataHandleBase.cxx new file mode 100644 index 0000000000000000000000000000000000000000..e6e03b6ebf0f9f2f6a8382d289010f1eac7c009f --- /dev/null +++ b/Control/SGTools/src/DataHandleBase.cxx @@ -0,0 +1,249 @@ +///////////////////////// -*- C++ -*- ///////////////////////////// + +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// DataHandleBase.cxx +// Implementation file for class DataHandleBase +// Author: S.Binet<binet@cern.ch> +/////////////////////////////////////////////////////////////////// + +// SGTools includes +#include "SGTools/DataHandleBase.h" + +// STL includes + + + +/////////////////////////////////////////////////////////////////// +// Public methods: +/////////////////////////////////////////////////////////////////// + +// Constructors +//////////////// + +/// Default constructor: +DataHandleBase::DataHandleBase() : + IResetable(), + m_itr(), + m_itrEnd(), + m_proxy(0), + //m_ptr(0), + m_useItr(false) +{} + +/// Copy constructor: +DataHandleBase::DataHandleBase( const DataHandleBase& rhs ) : + IResetable(), + m_itr(rhs.m_itr), + m_itrEnd(rhs.m_itrEnd), + m_proxy(rhs.m_proxy), + //m_ptr(rhs.m_ptr), + m_useItr(rhs.m_useItr) +{ + if (m_proxy) { + m_proxy->addRef(); + } +} + + +/// Assignment operator: +DataHandleBase& +DataHandleBase::operator=( const DataHandleBase& rhs ) +{ + if (this != &rhs) { + if (m_proxy) { + m_proxy->release(); + } + + m_itr = rhs.m_itr; + m_itrEnd = rhs.m_itrEnd; + m_useItr = rhs.m_useItr; + m_proxy = rhs.m_proxy; + //m_ptr = rhs.m_ptr; + if (m_proxy) { + m_proxy->addRef(); + } + } + + return *this; +} + +/// Constructor with parameters: +DataHandleBase::DataHandleBase(SG::DataProxy* proxy) : + IResetable(), + m_itr(), + m_itrEnd(), + m_proxy(proxy), + //m_ptr(0), + m_useItr(false) +{ + if (m_proxy) { + m_proxy->addRef(); + } +} + +DataHandleBase::DataHandleBase(const SG::ConstProxyIterator& itr, + const SG::ConstProxyIterator& itrEnd) : + IResetable(), + m_itr(itr), + m_itrEnd(itrEnd), + m_proxy(0), + //m_ptr(0), + m_useItr(true) +{ + if (m_itr != m_itrEnd) { + m_proxy = m_itr->second; + } + + if (m_proxy) { + m_proxy->addRef(); + } +} + + +/// Destructor: +DataHandleBase::~DataHandleBase() +{ + if (m_proxy != 0) { + m_proxy->unbindHandle(this); + m_proxy->release(); + } +} + +// Destructor +/////////////// + +/////////////////////////////////////////////////////////////////// +// Const methods: +/////////////////////////////////////////////////////////////////// + +StatusCode +DataHandleBase::setState(SG::ConstProxyIterator &itr, + const SG::ConstProxyIterator &itrEnd) const +{ + if (m_proxy) m_proxy->release(); + + m_itr = itr; + m_itrEnd = itrEnd; + m_useItr = true; + + // ouch! FIXME ? + // we could have a void* m_ptr data member and have a + // typeless_dataPointer method using the typeless machinery of + // DataProxy+DataBucketBase... + const_cast<DataHandleBase*>(this)->reset(); + + // scan from itr to itrEnd and set m_itr to the first valid iterator: + + for (; itr != itrEnd; itr++) { + if (itr->second->isValid()) { + m_itr = itr; + m_proxy = m_itr->second; + if (m_proxy) m_proxy->addRef(); + return StatusCode::SUCCESS; + } + } + + m_itr = itrEnd; + m_proxy = 0; + + return StatusCode::FAILURE; +} + +StatusCode +DataHandleBase::setState(SG::DataProxy* proxy) const +{ + if (0 == proxy || !proxy->isValid()) { + return StatusCode::FAILURE; + } + + if (m_proxy != proxy) { + if (m_proxy) m_proxy->release(); + m_proxy = proxy; + m_proxy->addRef(); + } + + m_useItr = false; + const_cast<DataHandleBase*>(this)->reset(); + + return StatusCode::SUCCESS; +} + +StatusCode +DataHandleBase::setState(IProxyDict* store, const ID_type& key) const +{ + if (0 == store) { + return StatusCode::FAILURE; + } + CLID cid = this->clid(); + SG::DataProxy* proxy = store->proxy(cid, key); + return this->setState(proxy); +} + +const std::string& +DataHandleBase::key() const +{ + if (m_itr == m_itrEnd) { + return m_proxy->name(); + } else { + return m_itr->first; + } +} + +bool +DataHandleBase::isConst() const +{ + return 0 != m_proxy + ? m_proxy->isConst() + : false; +} + + +// A weaker test that +// *does not* retrieve the GaudiObject to check validity if not already done +bool +DataHandleBase::isInitialized() const +{ + return (0 != m_proxy); +} + +/////////////////////////////////////////////////////////////////// +// Non-const methods: +/////////////////////////////////////////////////////////////////// + +StatusCode +DataHandleBase::setState(SG::DataProxy* proxy) +{ + if (0 == proxy || !proxy->isValid() || proxy->isConst()) { + return StatusCode::FAILURE; + } + + if (m_proxy != proxy) { + if (m_proxy) m_proxy->release(); + m_proxy = proxy; + m_proxy->addRef(); + } + + m_useItr = false; + this->reset(); + return StatusCode::SUCCESS; +} + +StatusCode +DataHandleBase::setState(IProxyDict* store, const ID_type& key) +{ + if (0 == store) { + return StatusCode::FAILURE; + } + CLID cid = this->clid(); + SG::DataProxy* proxy = store->proxy(cid, key); + return this->setState(proxy); +} + +/////////////////////////////////////////////////////////////////// +// Protected methods: +/////////////////////////////////////////////////////////////////// + + diff --git a/Control/SGTools/src/DataProxy.cxx b/Control/SGTools/src/DataProxy.cxx new file mode 100755 index 0000000000000000000000000000000000000000..a442d71accd5d6f6fc5b728db52b385ebb8b0ab6 --- /dev/null +++ b/Control/SGTools/src/DataProxy.cxx @@ -0,0 +1,345 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include <cassert> + +#include "AthenaKernel/IResetable.h" +#include "AthenaKernel/getMessageSvc.h" +#include "GaudiKernel/MsgStream.h" + +#include "GaudiKernel/DataObject.h" +#include "GaudiKernel/IConversionSvc.h" +#include "GaudiKernel/GenericAddress.h" +#include "SGTools/TransientAddress.h" +#include "SGTools/T2pMap.h" +#include "SGTools/DataBucketBase.h" +#include <stdexcept> +using SG::TransientAddress; + + +#include "SGTools/DataProxy.h" +using SG::DataProxy; + + +namespace { + ///sets pMember to pgref (resetting it if pgref is 0). Handles Gaudi refcount + template <class GAUDIREF> + void setGaudiRef(GAUDIREF* pgref, GAUDIREF*& pMember) { + if (0 != pgref) pgref->addRef(); + if (0 != pMember) pMember->release(); + pMember = pgref; + } + + ///resets pMember. Handles Gaudi refcount + template <class GAUDIREF> + void resetGaudiRef(GAUDIREF*& pMember) { setGaudiRef((GAUDIREF*)0, pMember); } + +} //end of unnamed namespace + +// Default Constructor +DataProxy::DataProxy(): + m_tAddress(new TransientAddress()), + m_refCount(0), + m_dObject(0), + m_dataLoader(0), + m_const(false), + m_origConst(false), + m_storageType(0), + m_resetFlag(true), + m_t2p(0), + m_errno(ALLOK), + m_store(0) +{ +} + +// DataProxy constructor with Transient Address +// (typically called from Proxy Provider) +DataProxy::DataProxy(TransientAddress* tAddr, + IConversionSvc* svc, + bool constFlag, bool resetOnly): + m_tAddress(tAddr), + m_refCount(0), + m_dObject(0), + m_dataLoader(svc), + m_const(constFlag), + m_origConst(constFlag), + m_storageType(0), + m_resetFlag(resetOnly), + m_t2p(0), + m_errno(ALLOK), + m_store(0) +{ + //assert( tAddr->clID() != 0 ); + if (svc) svc->addRef(); +} + +// with Data Object: +// (typically called from a StoreGate record +DataProxy::DataProxy(DataObject* dObject, + TransientAddress* tAddr, + bool constFlag, bool resetOnly): + m_tAddress(tAddr), + m_refCount(0), + m_dObject(0), + m_dataLoader(0), + m_const(constFlag), + m_origConst(constFlag), + m_storageType(0), + m_resetFlag(resetOnly), + m_t2p(0), + m_errno(ALLOK), + m_store(0) +{ + setObject(dObject); +} + +// Destructor +DataProxy::~DataProxy() +{ + resetGaudiRef(m_dataLoader); + resetGaudiRef(m_dObject); + delete m_tAddress; +} + +void DataProxy::setT2p(T2pMap* t2p) +{ + m_t2p = t2p; +} + + +/** + * @brief Mark this object as const. (Lock the object.) + * + * If the object held that derives from @c ILockable, then we also + * call @c lock on the object. + */ +void DataProxy::setConst() +{ + m_const = true; + lock(); +} + +bool DataProxy::bindHandle(IResetable* ir) { + if (ir->isSet()) { + return false; + } else { + m_handles.push_back(ir); + return true; + } +} + + + +void DataProxy::reset() +{ + + if (! m_handles.empty()) { resetBoundHandles(); } + + resetGaudiRef(m_dObject); + m_tAddress->reset(); + m_const = m_origConst; + +} + +/// don't need a comment +void DataProxy::resetBoundHandles() { + std::list<IResetable*>::iterator itre=m_handles.end(); + for (std::list<IResetable*>::iterator itr=m_handles.begin(); + itr != itre; ++itr) { + (*itr)->reset(); + } +} + +void DataProxy::unbindHandle(IResetable *ir) { + if( m_handles.empty() ) { return; } + m_handles.remove( ir ); +} + +/// return refCount +unsigned long DataProxy::refCount() const +{ + return m_refCount; +} + +/// Add reference to object +unsigned long DataProxy::addRef() +{ + return ++m_refCount; +} + +/// release reference to object +unsigned long DataProxy::release() +{ + unsigned long count(--m_refCount); + if ( 0 == count ) delete this; + return count; +} + + +///request to release the instance (may just reset it) +bool DataProxy::requestRelease(bool force /*= false*/) { + bool canRelease = !isResetOnly() || force; +#ifndef NDEBUG + MsgStream gLog(m_ims, "DataProxy"); + if (gLog.level() <= MSG::VERBOSE) { + gLog << MSG::VERBOSE << "requestRelease(): " + << (canRelease ? " release " : " reset") + <<" object " + << name() << " CLID " << clID() << " address " << MSG::hex + << object() << MSG::dec << endreq; + } +#endif + if (canRelease) release(); + else reset(); + return canRelease; +} + +/// set a DataObject address +void DataProxy::setObject(DataObject* dObject) +{ + setGaudiRef(dObject, m_dObject); + if (0 != m_dObject) { + m_dObject->setRegistry(this); + if (m_const) lock(); + } +} + + +// set IOpaqueAddress +void DataProxy::setAddress(IOpaqueAddress* address) +{ + m_tAddress->setAddress(address); +} +////////////////////////////////////////////////////////////// + +/// Access DataObject on-demand using conversion service +DataObject* DataProxy::accessData() +{ + if (0 != m_dObject) return m_dObject; // cached object + + if (0 == m_dataLoader) { + //MsgStream gLog(m_ims, "DataProxy"); + //gLog << MSG::WARNING + // << "accessData: IConversionSvc ptr not set" <<endreq; + m_errno=NOCNVSVC; + setObject(0); + return 0; + } + if (!isValidAddress()) { + MsgStream gLog(m_ims, "DataProxy"); + gLog << MSG::WARNING + << "accessData: IOA pointer not set" <<endreq; + m_errno=NOIOA; + setObject(0); + return 0; + } + + DataObject* obj(0); + StatusCode sc = m_dataLoader->createObj(m_tAddress->address(), obj); + + if ( sc.isSuccess() ) + { + setObject(obj); + DataBucketBase* bucket = dynamic_cast<DataBucketBase*>(obj); + if (bucket) { + void* payload = bucket->object(); + m_t2p->t2pRegister(payload, this); + m_errno=ALLOK; + + + // Register bases as well. + const SG::BaseInfoBase* bi = SG::BaseInfoBase::find (m_tAddress->clID()); + if (bi) { + std::vector<CLID> base_clids = bi->get_bases(); + for (unsigned i=0; i < base_clids.size(); i++) { + void* bobj = SG::DataProxy_cast (this, base_clids[i]); + if (bobj && bobj != payload) + m_t2p->t2pRegister (bobj, this); + } + } + } else { + MsgStream gLog(m_ims, "DataProxy"); + gLog << MSG::ERROR + << "accessData: ERROR registering object in t2p map" + <<m_tAddress->clID() << '/' << m_tAddress->name() << '\n' + <<" Returning NULL DataObject pointer " << endreq; + obj=0; + setObject(0); + m_errno=T2PREGFAILED; + } + } else { + MsgStream gLog(m_ims, "DataProxy"); + gLog << MSG::WARNING + << "accessData: conversion failed for data object " + <<m_tAddress->clID() << '/' << m_tAddress->name() << '\n' + <<" Returning NULL DataObject pointer " << endreq; + obj=0; + setObject(0); + m_errno=CNVFAILED; + } + + return obj; + +} + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +bool DataProxy::isValidAddress() const +{ + return (0 != m_tAddress && m_tAddress->isValid()); +} + +bool DataProxy::isValidObject() const +{ + // FIXME: should we try to chase? + return (0!= m_dObject); +} + +bool DataProxy::isValid() const +{ + return (isValidObject() || isValidAddress()); +} + + +/** + * @brief Try to get the pointer back from a @a DataProxy, + * converted to be of type @a clid. + * @param proxy The @a DataProxy. + * @param clid The ID of the class to which to convert. + * + * Only works if the held object is a @a DataBucket. + * Returns 0 on failure, + */ +void* SG::DataProxy_cast (SG::DataProxy* proxy, CLID clid) +{ + if (0 == proxy || !proxy->isValid()) + return 0; + DataObject* pObject = proxy->accessData(); + if (0 == pObject) + return 0; + return SG::Storable_cast (pObject, clid, proxy, proxy->isConst()); +} + + +/** + * @brief Register a transient object in a t2p map. + * @param trans The object to register. + */ +void DataProxy::registerTransient (void* p) +{ + if (m_t2p) + m_t2p->t2pRegister (p, this); +} + + +/** + * @brief Lock the data object we're holding, if any. + */ +void DataProxy::lock() +{ + DataBucketBase* bucket = dynamic_cast<DataBucketBase*>(m_dObject); + if (bucket) + bucket->lock(); +} + diff --git a/Control/SGTools/src/DataStore.cxx b/Control/SGTools/src/DataStore.cxx new file mode 100755 index 0000000000000000000000000000000000000000..035762c7654bceb22004dbb384158a463867dd42 --- /dev/null +++ b/Control/SGTools/src/DataStore.cxx @@ -0,0 +1,493 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "SGTools/DataStore.h" +#include "SGTools/DataProxy.h" +#include "SGTools/IStringPool.h" +#include "SGTools/exceptions.h" +#include "GaudiKernel/ClassID.h" +#include "GaudiKernel/MsgStream.h" +#include "GaudiKernel/Bootstrap.h" +#include "GaudiKernel/ISvcLocator.h" +#include "SGAudCore/ISGAudSvc.h" + +using namespace std; +using SG::DataStore; +using SG::DataProxy; +using SG::ProxyMap; +using SG::ProxyIterator; +using SG::ConstProxyIterator; + + +/** + * @brief Constructor. + * @param pool The string pool associated with this store. + */ +DataStore::DataStore (IProxyDictWithPool& pool) + : m_pool (pool), + m_storeMap(), m_storeID(StoreID::UNKNOWN), m_t2p(), + m_pSGAudSvc(0), m_noAudSvc(0), m_pSvcLoc(0) +{ + setSvcLoc().ignore(); +} + +//Destructor +DataStore::~DataStore() +{ + clearStore(); +} + +StatusCode DataStore::setSvcLoc(){ + StatusCode sc(StatusCode::FAILURE); + m_pSvcLoc = Gaudi::svcLocator( ); + if (!m_pSvcLoc) std::cout<<"DataStore::setSvcLoc: WARNING svcLocator not found! "<<std::endl; + return sc; +} + +void DataStore::setSGAudSvc() const { //m_noAudSvc and m_pSGAudSvc are mutable + if (0 == m_pSGAudSvc) { + //try once to get the service + const bool DONOTCREATE(false); + if (!m_noAudSvc) { + m_noAudSvc = m_pSvcLoc->service("SGAudSvc", m_pSGAudSvc, + DONOTCREATE).isFailure(); + } + } + return; +} + + +////////////////////////////////////////////////////////////// +void DataStore::clearStore(bool force /*= false*/, MsgStream* pmlog/*=0*/) +{ + + StoreIterator s_iter = m_storeMap.begin(); + StoreIterator s_end = m_storeMap.end(); + + for (; s_iter != s_end; s_iter++) + { + + ProxyMap& pmap = s_iter->second; + + ProxyIterator iter = pmap.begin(); + ProxyIterator end = pmap.end(); + + while (iter != end) { + + if (pmlog) { + *pmlog << MSG::VERBOSE + << "DataStore::clearStore() " + << (force ? "forcing" : "requesting") + << " release of DataProxy @" << iter->second + << ", recorded with key=" << iter->second->name() + << ", CLID=" << iter->second->clID() + << ", containing data object @" << iter->second->object(); + pmlog->flush(); //make sure this is printed now + } + if (iter->second->requestRelease(force)) { //request proxy deletion + //proxy was released, remove map entry + sgkey_t sgkey = m_pool.stringToKey (iter->first, s_iter->first); + m_keyMap.erase (sgkey); + + pmap.erase(iter++); //increment the pre-erase iterator (Effective STL Item 9) + } else { + //proxy was reset, keep map entry + ++iter; + } + if(pmlog) *pmlog << MSG::VERBOSE << " ... -> DONE" << endmsg; + } + } + + // clear T2PMap + m_t2p.clear(); +} + +///////////////////////////////////////////////////////////// +// access all the keys associated with an object: +// +void DataStore::keys(const CLID& id, std::vector<std::string>& vkeys, + bool includeAlias, bool onlyValid) +{ + vector<string> tkeys; + ProxyMap& pmap = m_storeMap[id]; + ConstProxyIterator p_iter = pmap.begin(); + for (; p_iter != pmap.end(); p_iter++) { + bool includeProxy(true); + if (onlyValid) includeProxy=p_iter->second->isValid(); + if (includeAlias) { + if (includeProxy) tkeys.push_back(p_iter->first); + } + else { + if (p_iter->first == p_iter->second->name() && includeProxy) + tkeys.push_back(p_iter->first); + } + } + vkeys.swap(tkeys); + return; +} + +////////////////////////////////////////////////////////////// +//---------------------------------------------------------------// +// record the proxy in StoreGate +StatusCode +DataStore::addToStore(const CLID& id, DataProxy* dp) +{ + StatusCode sc(StatusCode::FAILURE); + if (0 != dp) { + TransientAddress* tad = dp->transientAddress(); + + if (id == 0 && tad->clID() == 0 && tad->sgkey() != 0) { + // Handle a dummied proxy. + m_keyMap[tad->sgkey()] = dp; + } + else { + ProxyMap& pmap = m_storeMap[id]; + + // Set the primary key. + sgkey_t primary_sgkey = m_pool.stringToKey (tad->name(), tad->clID()); + tad->setSGKey (primary_sgkey); + + pmap.insert(ProxyMap::value_type(dp->name(), dp)); + + sgkey_t sgkey = primary_sgkey; + if (id != tad->clID()) + sgkey = m_pool.stringToKey (tad->name(), id); + m_keyMap[sgkey] = dp; + } + + // Note : No checking if proxy already exists in store because it + // is already checked in StoreGateSvc. + // if (pmap.find(dp->name()) == pmap.end()) { + dp->addRef(); // The store now owns this + dp->setT2p(&m_t2p); + dp->setStore(&m_pool); + + sc = StatusCode::SUCCESS; + // } else { + // std::cout << "!!!!!!!!!!!! Dupe found in store " << this << "CLID/KEY" << id << "/" << dp->name() << std::endl; + // } + } + return sc; + +} + +////////////////////////////////////////////////////////////////// +//---------------------------------------------------------------// +// if Proxy is a resettable proxy only then reset it, otherwise +// delete it and remove from proxy map. +StatusCode +DataStore::removeProxy(DataProxy* proxy, bool forceRemove) +{ + StatusCode sc(StatusCode::FAILURE); + if (0 == proxy) return sc; + + if (!forceRemove && proxy->isResetOnly()) { + proxy->reset(); + sc = StatusCode::SUCCESS; + } else { + + SG::DataProxy::CLIDCont_t clids = proxy->transientID(); + std::string name = proxy->name(); + sgkey_t primary_sgkey = proxy->transientAddress()->sgkey(); + + StoreIterator storeIter = m_storeMap.find(proxy->clID()); + if (storeIter != m_storeMap.end()) { + CLID clid = proxy->clID(); + // first remove the alias key: + ProxyMap& pmap = m_storeMap[clid]; + SG::DataProxy::AliasCont_t alias_set = proxy->alias(); + for (SG::DataProxy::AliasCont_t::const_iterator i = alias_set.begin(); + i != alias_set.end(); ++i) + { + m_keyMap.erase (m_pool.stringToKey (*i, clid)); + if (1 == pmap.erase(*i)) proxy->release(); + } + + // then remove the primary key + m_keyMap.erase (primary_sgkey); + if (1 == storeIter->second.erase(name)) { + proxy->release(); + sc = StatusCode::SUCCESS; + } + + // Remove all symlinks too. + for (SG::DataProxy::CLIDCont_t::const_iterator i = clids.begin(); + i != clids.end(); ++i) + { + storeIter = m_storeMap.find(*i); + if (storeIter != m_storeMap.end()) { + m_keyMap.erase (m_pool.stringToKey (name, *i)); + if (1 == storeIter->second.erase(name)) + proxy->release(); + } + } //symlinks loop + } //proxy there + } //reset only + return sc; +} + +////////////////////////////////////////////////////////////// +//---------------------------------------------------------------// +// record the symlink in StoreGate +StatusCode +DataStore::addSymLink(const CLID& linkid, DataProxy* dp) +{ + // Make sure the symlink doesn't already exist. + DataProxy* exist = proxy_exact (linkid, dp->name()); + if (exist == dp) { + // Entry already exists pointing at the desired proxy. + return StatusCode::SUCCESS; + } + else if (exist != 0) { + // Entry already exists pointing at another proxy. + // Don't change the existing entry. + return StatusCode::FAILURE; + } + + dp->transientAddress()->setTransientID(linkid); + return addToStore(linkid, dp); +} +//---------------------------------------------------------------// +// record the alias in StoreGate +StatusCode +DataStore::addAlias(const std::string& aliasKey, DataProxy* dp) +{ + // locate proxy map and add alias to proxymap + ProxyMap& pmap = m_storeMap[dp->clID()]; + + // check if another proxy for the same type caries the same alias. + // if yes, then remove that alias from that proxy and establish the + // alias in the new proxy. + // pmap.insert will overwrite, associate alias with new proxy. + ConstProxyIterator p_iter = pmap.find(aliasKey); + if (p_iter != pmap.end() && dp->clID() == p_iter->second->clID()) { + if (dp->name() == p_iter->second->name()) return StatusCode::SUCCESS; + p_iter->second->transientAddress()->removeAlias(aliasKey); + p_iter->second->release(); + } + // set alias in proxy + dp->transientAddress()->setAlias(aliasKey); + dp->addRef(); + pmap[aliasKey] = dp; + m_keyMap[m_pool.stringToKey (aliasKey, dp->clID())] = dp; + // pmap.insert(ProxyMap::value_type(aliasKey, dp)); + // use [] as it overwrites, .insert ignores second entry + + return StatusCode::SUCCESS; +} +//---------------------------------------------------------------// +// Count instances of TYPE in store +int DataStore::typeCount(const CLID& id) const +{ + ConstStoreIterator storeIter = m_storeMap.find(id); + if (storeIter == m_storeMap.end()) return 0; + return (storeIter->second).size(); +} + +//---------------------------------------------------------------// +// Return proxy for a given Transient Address +DataProxy* DataStore::proxy(const TransientAddress* tAddr) const +{ + return proxy(tAddr->clID(), tAddr->name()); +} + +// Return proxy for a given Transient ID (TYPE and KEY) +DataProxy* DataStore::proxy(const CLID& id, const std::string& key) const +{ + + // The logic here: if a key is specified, we locate it. + // If we don't find it and the default key (DEFAULTKEY) is specified, + // then we return any existing proxy for this type as long as there + // is exactly one, not counting aliases. More than one would be ambiguous + + ConstStoreIterator s_iter = m_storeMap.find(id); + DataProxy *p(0); + if (s_iter != m_storeMap.end()) + { + const ProxyMap& pmap = s_iter->second; + ConstProxyIterator p_iter = pmap.find(key); + if (p_iter != pmap.end()) { + p=p_iter->second; + + } else if (key == SG::DEFAULTKEY && !pmap.empty()) { + // we did not find the object using key. + // Now check for default object. + // Simple case first --- single object. + if (pmap.size() == 1) { + p = pmap.begin()->second; + } else { + // Otherwise, match only the exact type requested. + ConstProxyIterator p_match = pmap.end(); + size_t nmatch = 0; + for (p_iter = pmap.begin(); p_iter != pmap.end(); ++p_iter) { + if (p_iter->second->transientAddress()->clID() == id) { + ++nmatch; + if (p_match == pmap.end()) p_match = p_iter; + } + } + + // We must have matched only one object, not counting its aliases. + // Notice: we test that there are less than two matches: symlinked objects + // may carry aliases from the concrete class. In that case nmatch + // may be equal to or even smaller than the number of aliases + if (nmatch > 0 && + (int(nmatch - p_match->second->alias().size()) < 2)) + { + p = pmap.begin()->second; + } + } + } + else { + p = const_cast<DataStore*>(this)->findDummy (id, key); + } + } + else { + p = const_cast<DataStore*>(this)->findDummy (id, key); + } + + if (p && doAudit()) + m_pSGAudSvc->SGAudit(p->transientAddress()->name(), id, 0, m_storeID); + + return p; +} + + +/** + * @brief Look for (and convert) a matching dummy proxy. + * @param id The CLID for which to search. + * @param key The key for which to search. + * + * In some cases, we may enter into the store a `dummy' proxy, + * which is identified only by the hashed CLID/key pair. + * (This can happen when we have a link to an object that's not + * listed in the DataHeader; in this case, we know the only hashed key + * and not the CLID or key.) + * + * This function is called after we fail to find a proxy by CLID/key. + * It additionally checks to see if there exists a dummy proxy with + * a hash matching this CLID/key. If so, the CLID/key are filled + * in in the proxy, and the proxy is entered in m_storeMap. + * + * Returns either the matching proxy or 0. + */ +DataProxy* DataStore::findDummy (CLID id, const std::string& key) +{ + sgkey_t sgkey = m_pool.stringToKey (key, id); + DataProxy* p = proxy_exact (sgkey); + if (p) { + p->transientAddress()->setID (id, key); + ProxyMap& pmap = m_storeMap[id]; + if (!pmap.insert(ProxyMap::value_type(key, p)).second) { + // This shouldn't happen. + DataProxy* p2 = pmap[key]; + throw SG::ExcProxyCollision (id, key, p2->clID(), p2->name()); + } + } + return p; +} + + +/// get proxy with given key. Returns 0 to flag failure +/// the key must match exactly (no wild carding for the default key) +DataProxy* DataStore::proxy_exact(sgkey_t sgkey) const +{ + if (doAudit()) { + CLID clid; + const std::string* strkey = m_pool.keyToString (sgkey, clid); + if (strkey) + m_pSGAudSvc->SGAudit(*strkey, clid, 0, m_storeID); + } + KeyMap_t::const_iterator i = m_keyMap.find (sgkey); + if (i != m_keyMap.end()) + return i->second; + return 0; +} + + +/// get proxy with given key. Returns 0 to flag failure +/// the key must match exactly (no wild carding for the default key) +DataProxy* DataStore::proxy_exact(const CLID& id, + const std::string& key) const +{ + return proxy_exact (m_pool.stringToKey (key, id)); +} + + +//---------------------------------------------------------------// +// Return an iterator over proxies for a given CLID: +StatusCode DataStore::pRange(const CLID& id, ConstProxyIterator& pf, + ConstProxyIterator& pe) const +{ + static const ProxyMap emptyMap; + StatusCode sc(StatusCode::FAILURE); + + ConstStoreIterator storeIter = m_storeMap.find(id); + if (storeIter != m_storeMap.end()) + { + const ProxyMap& pmap = storeIter->second; + pf = pmap.begin(); + pe = pmap.end(); + if (pmap.size() > 0) sc = StatusCode::SUCCESS; + } else { + //keep valgrind happy + pf = emptyMap.end(); + pe = emptyMap.end(); + } + return sc; +} +//---------------------------------------------------------------// +// Return an iterator over the Store Map +StatusCode DataStore::tRange(ConstStoreIterator& tf, + ConstStoreIterator& te) const +{ + tf = m_storeMap.begin(); + te = m_storeMap.end(); + return StatusCode::SUCCESS; +} +//---------------------------------------------------------------// +// Build a list of proxies that are in the Store: +StatusCode DataStore::proxyList(std::list<DataProxy*>& plist) const +{ + ConstProxyIterator pf, pe; + ConstStoreIterator sf, se; + (tRange(sf, se)).ignore(); + for (; sf!=se; sf++) + { + (pRange(sf->first, pf, pe)).ignore(); + for (; pf!=pe; pf++) { + // FIXME : Check validity of proxy. + plist.push_back(pf->second); + } + } + return StatusCode::SUCCESS; +} +//---------------------------------------------------------------// +// locate Persistent Representation of a Transient Object +// +DataProxy* DataStore::locatePersistent(const void* const pTransient) const +{ + return m_t2p.locatePersistent(pTransient); +} + +////////////////////////////////////////////////////////////////// +StatusCode +DataStore::t2pRegister(const void* const pTrans, DataProxy* const pPers) +{ + std::string name=pPers->name(); + int i=name.find("/", 0); + name=name.erase(0,i+1); + + if (doAudit()) m_pSGAudSvc->SGAudit(name, pPers->clID(), 1, m_storeID); + + return (m_t2p.t2pRegister(pTrans, pPers)) ? + StatusCode::SUCCESS : + StatusCode::FAILURE; +} + + + + + + + diff --git a/Control/SGTools/src/IProxyDictWithPool.cxx b/Control/SGTools/src/IProxyDictWithPool.cxx new file mode 100644 index 0000000000000000000000000000000000000000..b8225f596e0ff980d9df1459cbccd5c27edfcb54 --- /dev/null +++ b/Control/SGTools/src/IProxyDictWithPool.cxx @@ -0,0 +1,34 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// $Id: IProxyDictWithPool.cxx,v 1.1 2008-04-18 03:18:24 ssnyder Exp $ +/** + * @file SGTools/src/IProxyDictWithPool.cxx + * @author scott snyder <snyder@bnl.gov> + * @date Mar, 2007 + * @brief Combine IProxyDict and IStringPool. + */ + + +#include "SGTools/IProxyDictWithPool.h" + + +/** + * @brief Test to see if the target of an ElementLink has moved. + * @param sgkey_in Original hashed key of the EL. + * @param index_in Original index of the EL. + * @param sgkey_out[out] New hashed key for the EL. + * @param index_out[out] New index for the EL. + * @return True if there is a remapping; false otherwise. + * + * The default implementation here always returns false. + */ +bool IProxyDictWithPool::tryELRemap (sgkey_t /*sgkey_in*/, + size_t /*index_in*/, + sgkey_t& /*sgkey_out*/, + size_t& /*index_out*/) +{ + return false; +} + diff --git a/Control/SGTools/src/SGFolderItem.cxx b/Control/SGTools/src/SGFolderItem.cxx new file mode 100755 index 0000000000000000000000000000000000000000..ef7d496b4a544116f24e63465a72959f57d5cf57 --- /dev/null +++ b/Control/SGTools/src/SGFolderItem.cxx @@ -0,0 +1,12 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "SGTools/SGFolderItem.h" + +bool +SG::FolderItem::isFolder() const { + return false; + //FIXME return (m_id == ClassID_traits<Folder>::ID()); +} + diff --git a/Control/SGTools/src/SGToolsClids.cxx b/Control/SGTools/src/SGToolsClids.cxx new file mode 100644 index 0000000000000000000000000000000000000000..0b2040e8555801042bbeedc45d8c56b0239107de --- /dev/null +++ b/Control/SGTools/src/SGToolsClids.cxx @@ -0,0 +1,9 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// anchor for the clids defined by this package + +#include "SGTools/BuiltinsClids.h" +#include "SGTools/StlMapClids.h" +#include "SGTools/StlVectorClids.h" diff --git a/Control/SGTools/src/SGVersionedKey.cxx b/Control/SGTools/src/SGVersionedKey.cxx new file mode 100644 index 0000000000000000000000000000000000000000..c035d35eeaf3ad069283f8e1dc0d59fecbbd57a2 --- /dev/null +++ b/Control/SGTools/src/SGVersionedKey.cxx @@ -0,0 +1,113 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <iostream> +#include <stdexcept> +#include <cassert> +#include "SGTools/SGVersionedKey.h" +using namespace SG; +using namespace std; + +VersionedKey::~VersionedKey() { + // if (m_versionKey) std::cout << "about to free " << + // m_versionKey << "@" << (void*)m_versionKey << + // "@this " << this << std::endl; + free(m_versionKey); +} + +bool +VersionedKey::isVersionedKey(const char * vkey) { + return (vkey[0]==separator() && vkey[3]==separator()); +} + +bool +VersionedKey::isVersionedKey(const std::string& vkey) { + return isVersionedKey(vkey.c_str()); +} + +VersionedKey::VersionedKey(const char* key, unsigned char version) { + encode(key, version); +} +VersionedKey::VersionedKey(const std::string& key, unsigned char version) { + encode(key.c_str(), version); +} +VersionedKey::VersionedKey(const std::string& versionedKey) { + copyVK(versionedKey.c_str()); +} +VersionedKey::VersionedKey(const char* versionedKey) { + copyVK(versionedKey); +} +VersionedKey::VersionedKey(const VersionedKey& versionedKey) : + m_versionKey(versionedKey.m_versionKey) { + versionedKey.m_versionKey=0; //a la auto-ptr +} +void VersionedKey::decode(char*& key, unsigned char& version) const { + key = m_versionKey+4; + version = (unsigned char)strtol(m_versionKey+1, NULL, 10); + assert(version <= 99); + // possibly faster, disgusting, version decoding + // equivalent to version = atoi(m_versionKey[2:3]); + // char *cptr(m_versionKey+1); + // if (*cptr>='0' && *cptr<='9') { + // version = 10 * (*cptr - '0'); + // ++cptr; + // if (*cptr>='0' && *cptr<='9') version += *cptr - '0'; + // else version = 0; + // } else version = 0; +} + +void VersionedKey::encode(const char* key, unsigned char version) { + assert(version <= 99); + m_versionKey = (char *)malloc(strlen(key)+5); + sprintf(m_versionKey, formatString(), version, key); +} + +void VersionedKey::copyVK(const char* versionedKey) { + if (isVersionedKey(versionedKey)) { + m_versionKey = (char *)malloc(strlen(versionedKey)+1); + strcpy(m_versionKey, versionedKey); + } + else { + encode(versionedKey, 0); + } +} +unsigned char VersionedKey::version() const { + return (unsigned char)strtol(m_versionKey+1, NULL, 10); +} +/// @returns base key +const char* VersionedKey::key() const { + return m_versionKey+4; +} + +bool +VersionedKey::sameKey(const VersionedKey& vkey) const { + return (0 == strcmp(this->key(),vkey.key())); +} + +bool +VersionedKey::sameKey(const std::string& baseKey) const { + return (0 == strcmp(this->key(),baseKey.c_str())); +} + +bool +VersionedKey::sameKey(const char* baseKey) const { + return (0 == strcmp(this->key(),baseKey)); +} + +/// sort according to highest key version +bool operator < (const SG::VersionedKey& lhs, const SG::VersionedKey& rhs) { + char *lhskey(0); + unsigned char lhsVersion(0); + lhs.decode(lhskey, lhsVersion); + unsigned char rhsVersion(0); + char *rhskey(0); + rhs.decode(rhskey, rhsVersion); + int keyCompare(strcmp(lhskey, rhskey)); + return ( ( keyCompare < 0) || + ( (keyCompare == 0) && (lhsVersion < rhsVersion) ) ) ; + +} diff --git a/Control/SGTools/src/StorableConversions.cxx b/Control/SGTools/src/StorableConversions.cxx new file mode 100755 index 0000000000000000000000000000000000000000..9f43eea2390729a37ebd2b75c6918b9cb62cf054 --- /dev/null +++ b/Control/SGTools/src/StorableConversions.cxx @@ -0,0 +1,78 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/** @file StorableConversions.cxx + * @brief convert to and from a SG storable + * $Id: StorableConversions.cxx,v 1.2 2008-04-08 16:05:32 ssnyder Exp $ + * @author ATLAS Collaboration + **/ + +#include "SGTools/StorableConversions.h" + + +namespace SG { + + +/** + * @brief Try to get the pointer back from a @a DataObject, + * converted to be of type @a clid. + * @param pDObj The @a DataObject. + * @param clid The ID of the class to which to convert. + * @param irt To be called if we make a new instance. + * @param isConst True if the object being converted is regarded as const. + * + * Only works if the @a DataObject is a @a DataBucket. + * Returns 0 on failure, + */ +void* fromStorable(DataObject* pDObj, CLID clid, + IRegisterTransient*irt/*= 0*/, + bool isConst /*= true*/) +{ + // Try to use BaseInfo information to convert pointers. + DataBucketBase* b = dynamic_cast<DataBucketBase*>(pDObj); + if (b) + return b->cast (clid, irt, isConst); + return 0; +} + + +/** + * @brief Try to get the pointer back from a @a DataObject, + * converted to be of type @a clid. + * @param pDObj The @a DataObject. + * @param clid The ID of the class to which to convert. + * @param irt To be called if we make a new instance. + * @param isConst True if the object being converted is regarded as const. + * + * Only works if the @a DataObject is a @a DataBucket. + * Returns 0 on failure, + */ +void* Storable_cast(DataObject* pDObj, CLID clid, + IRegisterTransient* irt /*= 0*/, + bool isConst /*= true*/) +{ + return fromStorable (pDObj, clid, irt, isConst); +} + + +/** + * @brief Try to get the pointer back from a @a DataObject, + * converted to be of type @a clid. + * @param pDObj The @a DataObject. + * @param clid The ID of the class to which to convert. + * @param irt To be called if we make a new instance. + * @param isConst True if the object being converted is regarded as const. + * + * Only works if the @a DataObject is a @a DataBucket. + * Returns 0 on failure, + */ +const void* Storable_cast(const DataObject* pDObj, CLID clid, + IRegisterTransient* irt /*= 0*/, + bool isConst /*= true*/) +{ + return fromStorable (const_cast<DataObject*> (pDObj), clid, irt, isConst); +} + + +} // namespace SG diff --git a/Control/SGTools/src/StringPool.cxx b/Control/SGTools/src/StringPool.cxx new file mode 100755 index 0000000000000000000000000000000000000000..6ebfe4b7dfd979ad15fc8cd902ebaef35e000a14 --- /dev/null +++ b/Control/SGTools/src/StringPool.cxx @@ -0,0 +1,224 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// $Id: StringPool.cxx,v 1.3 2007-12-10 22:20:03 ssnyder Exp $ +/** + * @file SGTools/StringPool.cxx + * @author scott snyder + * @date Mar 2007 + * @brief Maintain a mapping of strings to 64-bit ints. + */ + + +#include "SGTools/StringPool.h" +#include "SGTools/crc64.h" +#include "CxxUtils/unordered_map.h" +#include <map> +#include <cstdlib> +#include <iostream> +#include <iomanip> + + +namespace SG { + + +//*************************************************************************** +// Implementation class. +// + + +class StringPoolImpl +{ +public: + /// Remember an additional mapping from key to string. + bool registerKey (StringPool::sgkey_t key, + const std::string& str, + StringPool::sgaux_t aux); + + /// Find the string corresponding to a given key. + const std::string* keyToString (StringPool::sgkey_t key, + StringPool::sgaux_t& aux) const; + + /// Debugging dump. Write to stdout. + void dump() const; + +private: + // Hash function for the key. + // Just cast the low bits to a size_t. + struct keyhash + { + std::size_t operator() (StringPool::sgkey_t key) const + { return static_cast<std::size_t> (key); } + }; + + // The key hash table. + typedef std::pair<StringPool::sgaux_t, std::string> pair_t; + typedef SG::unordered_map<StringPool::sgkey_t, pair_t, keyhash> keymap_t; + keymap_t m_keymap; +}; + + +/** + * @brief Remember an additional mapping from key to string. + * @param key The key to enter. + * @param str The string to enter. + * @param aux Auxiliary data to include along with the string. + * @return True if successful; false if the @c key already + * corresponds to a different string. + */ +bool StringPoolImpl::registerKey (StringPool::sgkey_t key, + const std::string& str, + StringPool::sgaux_t aux) +{ + StringPoolImpl::keymap_t::iterator i = m_keymap.find (key); + if (i == m_keymap.end()) { + pair_t& p = m_keymap[key]; + p.first = aux; + p.second = str; + } + else if (i->second.first != aux || i->second.second != str) + return false; + return true; +} + + +/** + * @brief Find the string corresponding to a given key. + * @param key The key to look up. + * @param aux[out] Auxiliary data associated with the key. + * @return Pointer to the string found, or null. + * We can find keys as long as the corresponding string + * was given to either @c stringToKey() or @c registerKey(). + */ +const std::string* +StringPoolImpl::keyToString (StringPool::sgkey_t key, + StringPool::sgaux_t& aux) const +{ + StringPoolImpl::keymap_t::const_iterator i = m_keymap.find (key); + if (i != m_keymap.end()) { + aux = i->second.first; + return &i->second.second; + } + return 0; +} + + +/** + * @brief Debugging dump. Write to cout. + */ +void StringPoolImpl::dump() const +{ + for (keymap_t::const_iterator i = m_keymap.begin(); + i != m_keymap.end(); + ++i) + { + std::cout << std::hex << std::setw(18) << i->first << " " + << std::dec << std::setw(9) << i->second.first << " " + << i->second.second << "\n"; + } +} + + +//*************************************************************************** +// StringPool class. +// + +/** + * @brief Constructor. + */ +StringPool::StringPool() + : m_impl (new StringPoolImpl) +{ +} + + +/** + * @brief Destructor. + */ +StringPool::~StringPool() +{ + delete m_impl; +} + + +/** + * @brief Find the key for a string. + * @param str The string to look up. + * @param aux Auxiliary data to include along with the string. + * @return A key identifying the string. + * A given string will always return the same key. + * Will abort in case of a hash collision! + */ +StringPool::sgkey_t StringPool::stringToKey (const std::string& str, + sgaux_t aux /*= 0*/) +{ + uint64_t crc = crc64 (str); + if (aux) crc = crc64addint (crc, aux); + sgkey_t key = (crc & sgkey_t_max); + if (!m_impl->registerKey (key, str, aux)) + std::abort(); + return key; +} + + +/** + * @brief Find the string corresponding to a given key. + * @param key The key to look up. + * @return Pointer to the string found, or null. + * We can find keys as long as the corresponding string + * was given to either @c stringToKey() or @c registerKey(). + */ +const std::string* StringPool::keyToString (sgkey_t key) const +{ + sgaux_t aux; + return m_impl->keyToString (key, aux); +} + + +/** + * @brief Find the string corresponding to a given key. + * @param key The key to look up. + * @param aux[out] Auxiliary data associated with the key. + * @return Pointer to the string found, or null. + * We can find keys as long as the corresponding string + * was given to either @c stringToKey() or @c registerKey(). + */ +const std::string* StringPool::keyToString (sgkey_t key, + sgaux_t& aux) const +{ + return m_impl->keyToString (key, aux); +} + + +/** + * @brief Remember an additional mapping from key to string. + * @param key The key to enter. + * @param str The string to enter. + * @param aux Auxiliary data to include along with the string. + * @return True if successful; false if the @c key already + * corresponds to a different string. + * + * This registers an additional mapping from a key to a string; + * it can be found later through @c lookup() on the string. + */ +bool StringPool::registerKey (sgkey_t key, + const std::string& str, + sgaux_t aux /*= 0*/) +{ + // Make sure the primary mapping is registered first. + stringToKey (str, aux); + return m_impl->registerKey (key, str, aux); +} + + +/** + * @brief Debugging dump. Write to cout. + */ +void StringPool::dump () const +{ + m_impl->dump(); +} + + +} // namespace SG diff --git a/Control/SGTools/src/T2pMap.cxx b/Control/SGTools/src/T2pMap.cxx new file mode 100644 index 0000000000000000000000000000000000000000..03a7c3eaccb423cc803841703b43c69a49a69cbf --- /dev/null +++ b/Control/SGTools/src/T2pMap.cxx @@ -0,0 +1,17 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "SGTools/T2pMap.h" +using namespace SG; +std::vector<DataProxy*> T2pMap::pacReport() const { + std::vector<DataProxy*> notAccessed; + if (m_pac) { + t2p::const_iterator i(m_t2p.begin()), e(m_t2p.end()); + while (i != e) { + if (!m_pac->accessed(i->first)) notAccessed.push_back(i->second); + ++i; + } + } + return notAccessed; +} diff --git a/Control/SGTools/src/TransientAddress.cxx b/Control/SGTools/src/TransientAddress.cxx new file mode 100755 index 0000000000000000000000000000000000000000..5ad9091c0e64c6ecd9259da05de4230a754748f7 --- /dev/null +++ b/Control/SGTools/src/TransientAddress.cxx @@ -0,0 +1,95 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "SGTools/TransientAddress.h" +#include "AthenaKernel/IAddressProvider.h" +#include "GaudiKernel/IOpaqueAddress.h" + +#include <assert.h> + +using SG::TransientAddress; + +// Default Constructor: +TransientAddress::TransientAddress() + : m_clid(0), m_name(""), m_address(0), m_clearAddress(true), + m_consultProvider(false), m_pAddressProvider(0), m_storeID(StoreID::UNKNOWN), + m_sgkey(0) +{ } + +// Constructor with CLID and string key: +// (typically used through a StoreGate::record() +TransientAddress::TransientAddress(const CLID& id, const std::string& key) + : m_clid(id), m_name(key), m_address(0), m_clearAddress(true), + m_consultProvider(false), m_pAddressProvider(0), m_storeID(StoreID::UNKNOWN), + m_sgkey(0) +{ + if (id != CLID_NULL) + m_transientID.insert(id); +} + +// Constructor with CLID, string key and IOpaqueAddress: +// (typically used by a ProxyProvider) +TransientAddress::TransientAddress(const CLID& id, const std::string& key, + IOpaqueAddress* addr, + bool clearAddress) + : m_clid(id), m_name(key), m_address(0), m_clearAddress(clearAddress), + m_consultProvider(true), m_pAddressProvider(0), m_storeID(StoreID::UNKNOWN), + m_sgkey(0) +{ + if (id != CLID_NULL) + m_transientID.insert(id); + setAddress(addr); +} + +// Destructor +TransientAddress::~TransientAddress() +{ + setAddress(0); +} + + +/** + * @brief Set the CLID / key. + * @param id The new CLID. + * @param key The new StoreGate key. + * + * This will only succeed if the clid/key are currently clear. + */ +void TransientAddress::setID (CLID id, const std::string& key) +{ + assert (m_clid == CLID_NULL && m_name.empty() && m_transientID.empty() && + m_transientAlias.empty()); + m_clid = id; + m_name = key; + if (id != CLID_NULL) + m_transientID.insert(id); +} + +/// set IOpaqueAddress +void TransientAddress::setAddress(IOpaqueAddress* pAddress) +{ + if (0 != pAddress) pAddress->addRef(); + if (0 != m_address) m_address->release(); + m_address = pAddress; +} + +bool TransientAddress::isValid() +{ + if (0 != address()) return true; + + // FIXME CGL +// if (!m_consultProvider) { +// if ( m_clid != 0 && m_name != "" ) { return true; } +// } + if (m_consultProvider && 0 != provider()) { + if ((provider()->updateAddress(storeID(), this)).isSuccess()) + return true; + } + return false; +} + + + + + diff --git a/Control/SGTools/src/crc64.cxx b/Control/SGTools/src/crc64.cxx new file mode 100755 index 0000000000000000000000000000000000000000..6081bbec8a8c382e209084552d5ab1afa8bfe9e7 --- /dev/null +++ b/Control/SGTools/src/crc64.cxx @@ -0,0 +1,126 @@ +// $Id: crc64.cxx,v 1.2 2007-03-08 02:02:06 ssnyder Exp $ +/** + * @file SGTools/crc64.cxx + * @author scott snyder, originally from David T. Jones + * @date Mar 2007 + * @brief A CRC-64 implementation. + */ +/* + * Original comments: + * Improved calculation of CRC-64 values for protein sequences + * By David T. Jones (dtj@cs.ucl.ac.uk) - September 28th 2002 + * + * Modified from code at URL: + * ftp://ftp.ebi.ac.uk/pub/software/swissprot/Swissknife/old/SPcrc.tar.gz + * + * Changed to C++ and moved into a namespace. + */ + + +#include "SGTools/crc64.h" +#include <cstdio> +using namespace std; + + +// I don't have a citation for the source of this polynomial. +// Maybe should replace it with the ECMA DLT poly? +#define POLY64REV 0x95AC9329AC4BC9B5ULL +#define INITIALCRC 0xFFFFFFFFFFFFFFFFULL + +// Original SWISSPROT/TrEMBL poly. Shown to be weak. +//#define POLY64REV 0xd800000000000000ULL +//#define INITIALCRC 0x0000000000000000ULL + + +namespace { + +bool crc_init = false; +uint64_t CRCTable[256]; + +// Initialize the CRC table. +void init_table() +{ + crc_init = true; + for (int i = 0; i < 256; i++) + { + uint64_t part = i; + for (int j = 0; j < 8; j++) + { + if (part & 1) + part = (part >> 1) ^ POLY64REV; + else + part >>= 1; + } + CRCTable[i] = part; + } +} + +} // anonymous namespace + + +namespace SG { + + +/** + * @brief Find the CRC-64 of a string. + * @param str The string to hash. + */ +uint64_t crc64 (const std::string& str) +{ + if (!crc_init) + init_table(); + + uint64_t crc = INITIALCRC; + const char* seq = str.data(); + const char* end = seq + str.size(); + while (seq < end) + crc = CRCTable[(crc ^ *seq++) & 0xff] ^ (crc >> 8); + return crc; +} + + +/** + * @brief Extend a previously-calculated CRC to include an int. + * @param crc The previously-calculated CRC. + * @param x The integer to add. + * @return The new CRC. + */ +uint64_t crc64addint (uint64_t crc, unsigned int x) +{ + if (!crc_init) + init_table(); + + while (x > 0) { + crc = CRCTable[(crc ^ x) & 0xff] ^ (crc >> 8); + x >>= 8; + } + return crc; +} + + +/** + * @brief Format a CRC-64 as a string. + * @param crc The CRC to format. + */ +std::string crc64format (uint64_t crc) +{ + char buf[64]; + sprintf (buf, "%08X%08X", + (unsigned)((crc>>32)&0xffffffff), (unsigned)(crc&0xffffffff)); + return buf; +} + + +/** + * @brief Return a CRC-64 digest of a string. + * @param str The string to hash. + * @return The CRC-64 digest of the string. + * This is the hash code, expressed as hex as a string. + */ +std::string crc64digest (const std::string& str) +{ + return crc64format (crc64 (str)); +} + + +} // namespace SG diff --git a/Control/SGTools/src/exceptions.cxx b/Control/SGTools/src/exceptions.cxx new file mode 100644 index 0000000000000000000000000000000000000000..dad034bdd7b874e73a6261d2de9261e33d7ac80d --- /dev/null +++ b/Control/SGTools/src/exceptions.cxx @@ -0,0 +1,100 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// $Id$ +/** + * @file SGTools/src/exceptions.cxx + * @author scott snyder <snyder@bnl.gov> + * @date Nov, 2013 + * @brief Exceptions that can be thrown by SGTools. + */ + + +#include "SGTools/exceptions.h" +#include "GaudiKernel/System.h" +#include <sstream> +#include <string> + + +namespace SG { + + +/// Helper: Format exception string. +std::string excBadDataProxyCast_format (CLID id, const std::type_info& tid) +{ + std::ostringstream os; + os << "Bad cast of DataProxy with CLID " << id + << " to type " << System::typeinfoName (tid); + return os.str(); +} + + +/** + * @brief Constructor. + * @param id CLID of the DataProxy. + * @param tid Type to which we're trying to convert the object. + */ +ExcBadDataProxyCast::ExcBadDataProxyCast (CLID id, const std::type_info& tid) + : m_what (excBadDataProxyCast_format (id, tid)) +{ +} + + +/** + * @brief Return the message for this exception. + */ +const char* ExcBadDataProxyCast::what() const throw() +{ + return m_what.c_str(); +} + + +/** + * @brief Throw an ExcBadDataProxyCast exception. + * @param id CLID of the DataProxy. + * @param tid Type to which we're trying to convert the object. + */ +void throwExcBadDataProxyCast (CLID id, const std::type_info& tid) +{ + throw ExcBadDataProxyCast (id, tid); +} + + +//************************************************************************* + + +/// Helper: Format exception string. +std::string excProxyCollision_format (CLID id, + const std::string& key, + CLID primary_id, + const std::string& primary_key) +{ + std::ostringstream os; + os << "ExcProxyCollision: proxy collision for clid/key " + << id << " / " << key + << " (primary " << primary_id << " / " << primary_key << ")."; + return os.str(); +} + + +/** + * @brief Constructor. + * @param id CLID we're trying to set on the dummy proxy. + * @param key Key we're trying to set on the dummy proxy. + * @param primary_id CLID of the existing proxy. + * @param primary_key Key of the existing proxy. + */ +ExcProxyCollision::ExcProxyCollision (CLID id, + const std::string& key, + CLID primary_id, + const std::string& primary_key) + : std::runtime_error (excProxyCollision_format (id, + key, + primary_id, + primary_key)) +{ +} + + +} // namespace SG diff --git a/Control/SGTools/test/BaseInfo_test.cxx b/Control/SGTools/test/BaseInfo_test.cxx new file mode 100755 index 0000000000000000000000000000000000000000..b781bde748285487f3cb62e367b46cdba4684fad --- /dev/null +++ b/Control/SGTools/test/BaseInfo_test.cxx @@ -0,0 +1,341 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// $Id$ +/** + * @file SGTools/BaseInfo_test.cxx + * @author scott snyder + * @date A while ago. + * @brief Regression test for BaseInfo. + */ + + +#undef NDEBUG + +#include "SGTools/BaseInfo.h" +#include "SGTools/CLASS_DEF.h" +#include "boost/assign/list_of.hpp" +#include <iostream> +#include <algorithm> +#include <cassert> + +using std::cout; +using boost::assign::list_of; + +struct AA +{ + AA (int the_x=0): x(the_x) {} + ~AA() { } + int x; +}; +struct BB : public AA +{ + BB (int the_x=0) : AA(the_x) {} +}; +struct CC : public BB +{ + CC (int the_x=0) : BB(the_x) {} +}; + +SG_BASE(BB, AA); +SG_BASE(CC, BB); + +CLASS_DEF (AA, 1111, 2) +CLASS_DEF (BB, 1112, 2) +CLASS_DEF (CC, 1113, 2) + +struct M +{ + M (int the_x=0) : x(the_x) {} + virtual ~M() { } + int x; +}; +struct N : virtual public M +{ + N (int the_x=0) : M(the_x) {} +}; +struct O : virtual public M +{ + O (int the_x=0) : M(the_x) {} +}; +struct P : virtual public N, virtual public O +{ + P (int the_x=0) : M(the_x) {} +}; + +CLASS_DEF (M, 1114, 2) +CLASS_DEF (N, 1115, 2) +CLASS_DEF (O, 1116, 2) +CLASS_DEF (P, 1117, 2) + +SG_BASE (N, SG_VIRTUAL (M)); +SG_BASE (O, SG_VIRTUAL (M)); +SG_BASES2 (P, SG_VIRTUAL (N), SG_VIRTUAL (O)); + +struct X1 {}; +struct X2 : public X1 {}; +SG_BASE (X2, X1); + +struct Q : virtual public M +{ + Q (int the_x=0) : M(the_x) {} +}; +struct R : virtual public N, virtual public O, virtual public Q +{ + R (int the_x=0) : M(the_x) {} +}; + +CLASS_DEF (Q, 1118, 2) +CLASS_DEF (R, 1119, 2) + +SG_BASE (Q, SG_VIRTUAL (M)); +SG_BASES3 (R, SG_VIRTUAL (N), + SG_VIRTUAL (O), + SG_VIRTUAL (Q)); + + +struct I1 : public AA {}; +struct I2 : public AA {}; +SG_BASE (I1, AA); +SG_BASE (I2, AA); +CLASS_DEF (I2, 1120, 2) + +struct J : public AA, virtual public X1, public M {}; +SG_BASE(J, AA); +SG_ADD_BASE(J, SG_VIRTUAL(X1)); +SG_ADD_BASE(J, M); + +struct K : public AA {}; +SG_ADD_BASE(K, AA); + + +int test1() +{ + std::cout << "test1\n"; + + typedef SG::BaseInfo<CC> CC_C; + typedef SG::BaseInfo<R> R_C; + + std::vector<CLID> clids; + clids = CC_C::get_bases(); + std::vector<CLID> exp1 = list_of + (ClassID_traits<CC>::ID()) + (ClassID_traits<BB>::ID()) + (ClassID_traits<AA>::ID()); + std::sort (exp1.begin(), exp1.end()); + assert (clids == exp1); + + std::vector<const std::type_info*> tinfos; + tinfos = CC_C::get_ti_bases(); + std::vector<const std::type_info*> exp1ti = list_of + (&typeid(CC)) + (&typeid(BB)) + (&typeid(AA)); + std::sort (exp1ti.begin(), exp1ti.end()); + assert (tinfos == exp1ti); + + clids = R_C::get_bases(); + std::vector<CLID> exp2 = list_of + (ClassID_traits<M>::ID()) + (ClassID_traits<N>::ID()) + (ClassID_traits<O>::ID()) + (ClassID_traits<Q>::ID()) + (ClassID_traits<R>::ID()); + std::sort (exp2.begin(), exp2.end()); + assert (clids == exp2); + + tinfos = R_C::get_ti_bases(); + std::vector<const std::type_info*> exp2ti = list_of + (&typeid(M)) + (&typeid(N)) + (&typeid(O)) + (&typeid(Q)) + (&typeid(R)); + std::sort (exp2ti.begin(), exp2ti.end()); + assert (tinfos == exp2ti); + + SG::BaseInfoBase::castfn_t* castfn; + + M* m0 = new M; + R* r1 = new R; + M* m1 = r1; + assert ((long)m1 != (long)r1); + M* m2 = (M*)R_C::cast (r1, ClassID_traits<M>::ID()); + assert ((long)m1 == (long)m2); + m2 = (M*)R_C::cast (r1, typeid (M)); + assert ((long)m1 == (long)m2); + R* r2 = (R*)R_C::castTo (m1, ClassID_traits<M>::ID()); + assert ((long)r1 == (long)r2); + r2 = (R*)R_C::castTo (m1, typeid (M)); + assert ((long)r1 == (long)r2); + r2 = (R*)R_C::castTo (m0, typeid (M)); + assert (r2 == 0); + + castfn = R_C::castfn (ClassID_traits<M>::ID()); + assert ((long)m1 == (long)castfn(r1)); + castfn = R_C::castfn (typeid (M)); + assert ((long)m1 == (long)castfn(r1)); + castfn = R_C::castfnTo (ClassID_traits<M>::ID()); + assert ((long)r1 == (long)castfn(m1)); + castfn = R_C::castfnTo (typeid (M)); + assert ((long)r1 == (long)castfn(m1)); + assert (0 == (long)castfn(m0)); + + assert (R_C::cast (r1, ClassID_traits<AA>::ID()) == 0); + assert (R_C::cast (r1, typeid (AA)) == 0); + assert (R_C::castTo (r1, ClassID_traits<AA>::ID()) == 0); + assert (R_C::castTo (r1, typeid (AA)) == 0); + assert (R_C::castfn (ClassID_traits<AA>::ID()) == 0); + assert (R_C::castfn (typeid (AA)) == 0); + assert (R_C::castfnTo (ClassID_traits<AA>::ID()) == 0); + assert (R_C::castfnTo (typeid (AA)) == 0); + + assert (R_C::is_base (ClassID_traits<M>::ID())); + assert (R_C::is_base (typeid (M))); + + assert (!R_C::is_base (ClassID_traits<AA>::ID())); + assert (!R_C::is_base (typeid (AA))); + + assert (CC_C::is_base (ClassID_traits<AA>::ID())); + assert (CC_C::is_base (typeid (AA))); + + assert (R_C::is_virtual (ClassID_traits<M>::ID())); + assert (R_C::is_virtual (typeid (M))); + + assert (!CC_C::is_virtual (ClassID_traits<AA>::ID())); + assert (!CC_C::is_virtual (typeid (AA))); + + typedef SG::BaseInfo<X2> X_C; + assert (X_C::is_base (typeid (X1))); + X2* x2 = new X2; + X1* x1 = (X1*)X_C::cast (x2, typeid (X1)); + assert (x1 == x2); + X2* x2a = (X2*)X_C::castTo (x1, typeid (X1)); + assert (x2a == 0); // castTo doesn't work now for non-polymorphic classes. + + clids = SG::BaseInfoBase::find (ClassID_traits<CC>::ID())->get_bases(); + assert (clids == exp1); + tinfos = SG::BaseInfoBase::find (ClassID_traits<CC>::ID())->get_ti_bases(); + assert (tinfos == exp1ti); + + clids = CC_C::baseinfo().get_bases(); + assert (clids == exp1); + tinfos = CC_C::baseinfo().get_ti_bases(); + assert (tinfos == exp1ti); + + clids = SG::BaseInfoBase::find (typeid (CC))->get_bases(); + assert (clids == exp1); + tinfos = SG::BaseInfoBase::find (typeid (CC))->get_ti_bases(); + assert (tinfos == exp1ti); + + assert (SG::BaseInfoBase::find (typeid(CC))->clid() == + ClassID_traits<CC>::ID()); + assert (SG::BaseInfoBase::find (typeid(CC))->typeinfo() == typeid(CC)); + + assert (SG::BaseInfoBase::find (99999) == 0); + assert (SG::BaseInfoBase::find (typeid(int)) == 0); + + assert (typeid(SG::BaseType<SG::Bases<BB>::Base1>::type) == typeid(AA)); + assert (typeid(SG::BaseType<SG::Bases<BB>::Base1>::is_virtual) == + typeid(boost::false_type)); + + assert (typeid(SG::BaseType<SG::Bases<N>::Base1>::type) == typeid(M)); + assert (typeid(SG::BaseType<SG::Bases<N>::Base1>::is_virtual) == + typeid(boost::true_type)); + + std::vector<CLID> exp3 = list_of + (ClassID_traits<AA>::ID()); + clids = SG::BaseInfoBase::find (typeid (I1))->get_bases(); + assert (clids == exp3); + + std::vector<const std::type_info*> exp3ti = list_of + (&typeid (AA)) + (&typeid (I1)); + std::sort (exp3ti.begin(), exp3ti.end()); + tinfos = SG::BaseInfoBase::find (typeid (I1))->get_ti_bases(); + assert (tinfos == exp3ti); + + std::vector<CLID> exp4 = list_of + (ClassID_traits<AA>::ID()) + (ClassID_traits<I2>::ID()); + clids = SG::BaseInfoBase::find (ClassID_traits<I2>::ID())->get_bases(); + assert (clids == exp4); + + std::vector<const std::type_info*> exp4ti = list_of + (&typeid (AA)) + (&typeid (I2)); + std::sort (exp4ti.begin(), exp4ti.end()); + tinfos = SG::BaseInfoBase::find (typeid (I2))->get_ti_bases(); + assert (tinfos == exp4ti); + + const SG::BaseInfoBase* jbib = SG::BaseInfoBase::find (typeid (J)); + tinfos = jbib->get_ti_bases(); + std::vector<const std::type_info*> exp5ti = list_of + (&typeid (AA)) + (&typeid (X1)) + (&typeid (M)) + (&typeid (J)); + std::sort (exp5ti.begin(), exp5ti.end()); + std::sort (tinfos.begin(), tinfos.end()); + assert (tinfos == exp5ti); + assert (!jbib->is_virtual (typeid (AA))); + assert ( jbib->is_virtual (typeid (X1))); + assert (!jbib->is_virtual (typeid (M))); + + const SG::BaseInfoBase* kbib = SG::BaseInfoBase::find (typeid (K)); + tinfos = kbib->get_ti_bases(); + std::vector<const std::type_info*> exp6ti = list_of + (&typeid (AA)) + (&typeid (K)); + std::sort (exp6ti.begin(), exp6ti.end()); + std::sort (tinfos.begin(), tinfos.end()); + assert (tinfos == exp6ti); + + return 0; +} + + +class KCopyConversion + : public SG::CopyConversion<K, M> +{ +public: + void convert (const K& src, M& dst) const + { dst.x = src.x; } +}; + +SG_ADD_COPY_CONVERSION(K, KCopyConversion); + + +// Test copying conversions. +void test2() +{ + std::cout << "test2\n"; + const SG::BaseInfoBase& bib = SG::BaseInfo<K>::baseinfo(); + std::vector<CLID> clids = bib.get_copy_conversions(); + std::vector<CLID> exp1 = list_of + (ClassID_traits<M>::ID()); + assert (clids == exp1); + + const SG::CopyConversionBase* b = bib.copy_conversion (clids[0]); + assert (b == bib.copy_conversion (typeid (M))); + assert (0 == bib.copy_conversion (typeid (X1))); + assert (0 == bib.copy_conversion (typeid (Q))); + assert (0 == bib.copy_conversion (ClassID_traits<Q>::ID())); + + K k; + k.x = 10; + M m; + m.x = 0; + b->convertUntyped (&k, &m); + assert (m.x == 10); +} + + +int main() +{ + test1(); + test2(); + return 0; +} + diff --git a/Control/SGTools/test/CLIDRegistry_test.cxx b/Control/SGTools/test/CLIDRegistry_test.cxx new file mode 100755 index 0000000000000000000000000000000000000000..739f122682c46b041cc60973ca13e09bbdf4e969 --- /dev/null +++ b/Control/SGTools/test/CLIDRegistry_test.cxx @@ -0,0 +1,52 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/** @file CLIDRegistry_test.cxx + * @brief unit test for CLIDRegistry + * + * $Id: CLIDRegistry_test.cxx,v 1.2 2009-01-19 17:02:55 binet Exp $ + * @author Paolo Calafiura <pcalafiura@lbl.gov> - ATLAS Collaboration + */ + +/* #define COMPILEFAIL 1 */ + +#undef NDEBUG + +#include "SGTools/CLIDRegistry.h" + +#include <algorithm> +#include <cassert> +#include <iostream> + +using namespace std; + +#include <boost/tuple/tuple.hpp> +using boost::get; +#include "AthenaKernel/tools/AthenaPackageInfo.h" + +int main () { + cerr << "*** CLIDRegistry_test starts ***" <<endl; + //reset newEntries before we start counting + std::pair<CLIDRegistry::const_iterator, CLIDRegistry::const_iterator> er = + CLIDRegistry::newEntries(); + Athena::PackageInfo info(PACKAGE_VERSION); +#ifdef COMPILEFAIL + CLIDRegistry::addEntry<12>("Foo", info, "Foo"); + //no upper limit CLIDRegistry::addEntry<1245736740>("Foo", info); +#endif + CLIDRegistry::addEntry<1234>("Foo", info, "Foo"); + CLIDRegistry::addEntry<4321>("Bar", info, "Bar"); + assert(CLIDRegistry::hasNewEntries()); + er = CLIDRegistry::newEntries(); + assert( distance(er.first, er.second) == 2 ); + assert( get<0>(*(CLIDRegistry::end()-2)) == 1234 ); + assert( get<1>(*(CLIDRegistry::end()-2)) == "Foo" ); + assert( get<2>(*(CLIDRegistry::end()-2)).name() == "SGTools" ); + CLIDRegistry::addEntry<43213>("Baz", info, "Baz"); + er = CLIDRegistry::newEntries(); + assert( distance(er.first, er.second) == 1 ); + assert( !CLIDRegistry::hasNewEntries()); + cerr << "*** CLIDRegistry_test OK ***" <<endl; + return 0; +} diff --git a/Control/SGTools/test/ClassName_test.cxx b/Control/SGTools/test/ClassName_test.cxx new file mode 100755 index 0000000000000000000000000000000000000000..efd1eebcd8063f62d3cb014547ac73ea105f2d83 --- /dev/null +++ b/Control/SGTools/test/ClassName_test.cxx @@ -0,0 +1,25 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include <cassert> +#include "SGTools/ClassName.h" + +class A {}; +class B {}; +template <class T> class C {}; + +template <> +class ClassName<B> +{ +public: + static std::string name() { return "fooB"; } +}; + +int main() +{ + assert (ClassName<A>::name() == "A"); + assert (ClassName<C<C<A> > >::name() == "C<C<A> >"); + assert (ClassName<B>::name() == "fooB"); + return 0; +} diff --git a/Control/SGTools/test/DataBucket_test.cxx b/Control/SGTools/test/DataBucket_test.cxx new file mode 100755 index 0000000000000000000000000000000000000000..14de4c273c28f7b197380a16a2b6b20e0bd64614 --- /dev/null +++ b/Control/SGTools/test/DataBucket_test.cxx @@ -0,0 +1,408 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#undef NDEBUG + +#include "SGTools/BuiltinsClids.h" +#include "SGTools/StlVectorClids.h" +#include "SGTools/StlMapClids.h" +#include "SGTools/DataBucket.h" +#include "SGTools/StorableConversions.h" +#include "AthenaKernel/ILockable.h" +#include <iostream> +using namespace std; +using namespace SG; + +/*FIXME can get it from TestTools circ package dep */ +#include <cassert> +#define SGASSERTERROR( FALSEEXPR ) \ + std::cerr << "Now we expect to see an error message:" << std::endl \ + << "----Error Message Starts--->>" << std::endl; \ + assert(!FALSEEXPR); \ + std::cerr<< "<<---Error Message Ends-------" << std::endl + + +#include "GaudiKernel/DataObject.h" +class GaudiDataObj : public DataObject { + +public: + static int count; + + GaudiDataObj(): DataObject(), m_val(0) { ++count; }; + GaudiDataObj(int i): DataObject(), m_val(i) { ++count; }; + virtual ~GaudiDataObj(){ --count; }; + + static const CLID& classID() { + static const CLID _ID = 8010; + return _ID; } + virtual const CLID& clID() const { return classID(); } + + void val(int i) { m_val = i; } + int val() const { return m_val; } + +private: + int m_val; +}; +int GaudiDataObj::count = 0; + +class WrongType {}; + +class AbstractType { +public: + virtual ~AbstractType() {} + virtual void abstractMethod()=0; +}; + +class AbstractDataObj : public DataObject { +public: + static const CLID& classID() { + static const CLID _ID = 8011; + return _ID; } + virtual const CLID& clID() const { return classID(); } + virtual void abstractMethod()=0; +}; + +class MyDataObj { + +public: + static int count; + + MyDataObj(): m_val(0) { ++count; }; + MyDataObj(int i): m_val(i) { ++count; } + ~MyDataObj(){ --count; } + + void val(int i) { m_val = i; } + int val() const { return m_val; } + +private: + int m_val; +}; +int MyDataObj::count = 0; + +#include "SGTools/CLASS_DEF.h" +CLASS_DEF(MyDataObj, 8000, 3) + +#include <cassert> +#include <vector> +#include <map> + +#include "TestTools/initGaudi.h" + +//CLASSID_DEF(int, 34) +//CLASSVERSION_DEF(int, 5) +// CLASS_DEF(int, 8105, 1) +// CLASS_DEF(std::vector<int>, 8002, 1) +// CLASS_DEF2(std::map<int, float>, 8003, 1) +CLASS_DEF(AbstractType, 8004, 1) +CLASS_DEF(WrongType, 8005, 1) + +struct X1 +{ + ~X1() {} + int a; +}; + +struct X2 + : public virtual X1 +{ + int b; +}; + +CLASS_DEF(X1, 8011, 1) +CLASS_DEF(X2, 8012, 1) +SG_BASE(X2, X1); + +CLASS_DEF( const int* , 206871866 , 1 ) + +class X3 +{ +public: + int a; +}; +CLASS_DEF(X3, 8013, 1) + + +class XCopyConversion + : public SG::CopyConversion<X1, X3> +{ +public: + void convert (const X1& src, X3& dst) const + { dst.a = src.a; } +}; + +SG_ADD_COPY_CONVERSION(X1, XCopyConversion); + +class X4 +{ +public: + int a; +}; +CLASS_DEF(X4, 8014, 1) + + +class X5 +{ +public: + X5 (int the_a) : a(the_a){} + ~X5() { log.push_back (a); } + int a; + static std::vector<int> log; +}; +std::vector<int> X5::log; +CLASS_DEF(X5, 8015, 1) + + +class XLock : public ILockable +{ +public: + XLock() : m_locked (false) {} + void lock() { m_locked = true; std::cout << "lock\n"; } + bool m_locked; +}; +CLASS_DEF(XLock, 8114, 1) + + + +class TestRegisterTransient + : public IRegisterTransient +{ +public: + virtual void registerTransient (void* trans) { m_xtrans.push_back (trans); } + + std::vector<void*> m_xtrans; +}; + + + +// Test copying conversion. +void test2() +{ + std::cout << "test2\n"; + TestRegisterTransient trt; + + X1* x1 = new X1; + x1->a = 10; + DataObject* xbucket = asStorable(x1); + + const X3* x3 = Storable_cast<X3>(xbucket, false, &trt); + assert ((char*)x3 != (char*)x1); + assert (x3->a == 10); + + assert (trt.m_xtrans.size() == 1); + assert (trt.m_xtrans[0] == x3); + + const X4* x4 = Storable_cast<X4>(xbucket, true, &trt); + assert (x4 == 0); + + assert (Storable_cast<X3>(xbucket, false, &trt, false) == 0); + + SG::DataBucket<X1>* xb = dynamic_cast<SG::DataBucket<X1>*> (xbucket); + assert (xb->cast (ClassID_traits<X3>::ID(), &trt) == x3); + assert (xb->cast (typeid(X3), &trt) == x3); + + assert (xb->cast (ClassID_traits<X4>::ID(), &trt) == 0); + assert (xb->cast (typeid(X4), &trt) == 0); + + assert (xb->cast (ClassID_traits<X3>::ID(), &trt, false) == 0); + assert (xb->cast (typeid(X3), &trt, false) == 0); +} + + +// Test lock() +void test3() +{ + std::cout << "test3\n"; + + X1* x1 = new X1; + XLock* xlock = new XLock; + + DataObject* b1 = asStorable (x1); + DataObject* b2 = asStorable (xlock); + + DataBucketBase* bb1 = dynamic_cast<DataBucketBase*> (b1); + DataBucketBase* bb2 = dynamic_cast<DataBucketBase*> (b2); + + bb1->lock(); + assert (!xlock->m_locked); + bb2->lock(); + assert (xlock->m_locked); +} + + +int main () { + ISvcLocator* pDum; + Athena_test::initGaudi(pDum); //need the MessageSvc + assert( pDum ); + DataBucket<int> intBucket(0); + DataBucket<const int*> pintBucket(0); + DataBucket<vector<int> > vintBucket(0); + cerr << "int has_classID " << intBucket.clID() << " version " + << ClassID_traits<int>::s_version << " and " + << (ClassID_traits<int>::s_isDataObject ? "does" : "does not") + << " inherit from DataObject" <<endl; + cerr << "const int* has_classID " << pintBucket.clID() <<endl; + assert(intBucket.clID() == pintBucket.clID()); + + cerr << "vector<int> has_classID " << vintBucket.clID() <<endl; + DataBucket<GaudiDataObj> gdobjBucket(0); + cerr << "GaudiDataObj has_classID " << gdobjBucket.clID() << " and " + << (ClassID_traits<GaudiDataObj>::s_isDataObject ? "does" : "does not") + << " inherit from DataObject" <<endl; + assert(gdobjBucket.clID() == GaudiDataObj::classID()); + assert(ClassID_traits<GaudiDataObj>::s_isDataObject); + + DataBucket<MyDataObj> dobjBucket(0); + cerr << "MyDataObj has_classID " << dobjBucket.clID() << " and " + << (ClassID_traits<MyDataObj>::s_isDataObject ? "does" : "does not") + << " inherit from DataObject" <<endl; + assert(dobjBucket.clID() == ClassID_traits<MyDataObj>::ID()); + assert(!ClassID_traits<MyDataObj>::s_isDataObject); + + DataBucket<AbstractDataObj> absdobjBucket(0); + cerr << "AbstractDataObj has_classID " << absdobjBucket.clID() <<endl; + assert(absdobjBucket.clID() == AbstractDataObj::classID()); + assert(ClassID_traits<AbstractDataObj>::s_isDataObject); + + DataBucket<AbstractType> absBucket(0); + cerr << "AbstractType has_classID " << absBucket.clID() <<endl; + assert(absBucket.clID() == ClassID_traits<AbstractType>::ID()); + assert(!ClassID_traits<AbstractType>::s_isDataObject); + + assert("int" == ClassID_traits<int>::typeName()); + assert("GaudiDataObj" == ClassID_traits<GaudiDataObj>::typeName()); + if("std::map<int,float>" != + ClassID_traits<map<int, float> >::typeName()) { + cerr << "error checking type name for map<int,float>: ClassID has it as " << ClassID_traits<map<int, float> >::typeName() <<endl; + assert(0); + } + + MyDataObj* pMDO = new MyDataObj(1); + MyDataObj* pRes(0); + + DataObject* pBucket(asStorable(pMDO)); + assert(fromStorable(pBucket, pRes)); + //FIXME asStorable above creates a DataBucket which is not deleted by anybody + WrongType* pWrong(0); + SGASSERTERROR(fromStorable(pBucket, pWrong)); + assert(pMDO == pRes); + assert(pRes->val()==1); + + pRes = 0; + // static const bool QUIET(true); + static const bool VERBOSE(false); + assert(0 != (pRes = Storable_cast<MyDataObj>(pBucket, VERBOSE))); + + cerr << "Now we expect to see an error message:" << endl + << "----Error Message Starts--->>" << endl; + pWrong = Storable_cast<WrongType>(pBucket, VERBOSE); + assert(0 == pWrong); + cerr<< "<<---Error Message Ends-------" << endl; + cerr << "Now we expect to see an error message:" << endl + << "----Error Message Starts--->>" << endl; + pWrong = Storable_cast<WrongType>((DataObject*)0); + assert(0 == pWrong); + cerr<< "<<---Error Message Ends-------" << endl; + delete pBucket; + + GaudiDataObj* pGDO = new GaudiDataObj(2); + GaudiDataObj* pGRes(0); + DataObject* DBGDO(asStorable(pGDO)); + assert(fromStorable(DBGDO, pGRes)); + SGASSERTERROR(fromStorable(DBGDO, pWrong)); + assert(pGDO == pGRes); + assert(pGRes->val()==2); + + DataObject* pDO(0); + assert (0 != (pDO = asStorable(new GaudiDataObj(3)))); + pGRes = 0; + assert(0 != (pGRes = Storable_cast<GaudiDataObj>(pDO, VERBOSE))); + + const DataObject& rDO(*pDO); + const GaudiDataObj& rGRes(Storable_cast<GaudiDataObj>(rDO, VERBOSE)); + + try { + cerr << "Now we expect to see an error message:" << endl + << "----Error Message Starts--->>" << endl; + const WrongType& rWr = Storable_cast<WrongType>(rGRes, VERBOSE); + pWrong=const_cast<WrongType*>(&rWr); //remove warning + } catch (bad_Storable_cast ) { + cerr << "<<---Error Message Ends-------" << endl; + } + + const DataObject* cpDO(pDO); + const GaudiDataObj* cpGRes(Storable_cast<GaudiDataObj>(cpDO, VERBOSE)); + assert( 0 != cpGRes ); + delete pDO; + delete DBGDO; + + //---------------------------------------------------------- + X2* x2 = new X2; + X1* x1 = x2; + assert ((long)x1 != (long)x2); + DataObject* xbucket = asStorable(x2); + X1* x1b = 0; + assert (fromStorable (xbucket, x1b)); + assert (x1 == x1b); + delete xbucket; + //---------------------------------------------------------- + // Test refcounting. + int c1 = GaudiDataObj::count; + int c2 = MyDataObj::count; + GaudiDataObj* gdo = new GaudiDataObj; + assert(1 == gdo->addRef()); + DataBucketBase* b1 = dynamic_cast<DataBucketBase*>(asStorable(gdo)); + assert(1 == b1->addRef()); + assert(1 == b1->refCount()); + assert(2 == gdo->refCount()); //notice how DB and DO have indep refcounts + assert(1 == gdo->release()); + assert(1 == gdo->refCount()); + assert(1 == b1->refCount()); + assert(0 == b1->release()); + assert (c1 == GaudiDataObj::count); + //another combination + gdo = new GaudiDataObj; + assert(1 == gdo->addRef()); + DataObject* b2(asStorable(gdo)); + assert(3 == gdo->addRef()); + delete b2; //this must not delete gdo, only decrease its refcount + assert(2 == gdo->refCount()); + assert (c1 + 1 == GaudiDataObj::count); + //this is simpler: no DataObj in play + b2 = asStorable(new MyDataObj); + delete b2; + assert (c2 == MyDataObj::count); + //cleanup + delete gdo; + //---------------------------------------------------------- + +#if __cplusplus > 201100 + { + std::unique_ptr<X5> p (new X5(10)); + DataBucketBase* b3 = new DataBucket<X5> (std::move(p)); + assert (p.get() == 0); + assert (X5::log.empty()); + delete b3; + assert (X5::log == std::vector<int> {10}); + X5::log.clear(); + } + + { + std::unique_ptr<X5> p (new X5(11)); + DataObject* b4 = asStorable (std::move(p)); + assert (p.get() == 0); + assert (X5::log.empty()); + delete b4; + assert (X5::log == std::vector<int> {11}); + } +#endif + + test2(); + test3(); + + cerr << "*** DataBucket_test OK ***" <<endl; + return 0; + +} + + diff --git a/Control/SGTools/test/DataProxy_test.cxx b/Control/SGTools/test/DataProxy_test.cxx new file mode 100644 index 0000000000000000000000000000000000000000..71de6e5829ceae0230011fab6f00790e8f77e3ab --- /dev/null +++ b/Control/SGTools/test/DataProxy_test.cxx @@ -0,0 +1,133 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// $Id$ +/** + * @file DataProxy_test.cxx + * @author scott snyder <snyder@bnl.gov> + * @date Nov, 2013 + * @brief Regression tests for DataProxy. + */ + +#undef NDEBUG +#include "SGTools/DataProxy.h" +#include "SGTools/IProxyDictWithPool.h" +#include "SGTools/StorableConversions.h" +#include "SGTools/CLASS_DEF.h" +#include "AthenaKernel/ILockable.h" +#include <iostream> +#include <cstdlib> +#include <cassert> + + +struct X1 +{ + ~X1() {} +}; +CLASS_DEF(X1, 8011, 1) + +class XLock : public ILockable +{ +public: + XLock() : m_locked (false) {} + void lock() { m_locked = true; std::cout << "lock\n"; } + bool m_locked; +}; +CLASS_DEF(XLock, 8114, 1) + +class TestStore + : public IProxyDictWithPool +{ +public: + unsigned long addRef() + { std::cout << "addRef\n"; std::abort(); } + unsigned long release() + { std::cout << "release\n"; std::abort(); } + StatusCode queryInterface(const InterfaceID &/*ti*/, void** /*pp*/) + { std::cout << "queryInterface\n"; std::abort(); } + const std::string& name() const + { std::cout << "name\n"; std::abort(); } + + + SG::DataProxy* deep_proxy(const void* const /*pTransient*/) const + { std::cout << "deep_proxy\n"; std::abort(); } + SG::DataProxy* proxy(const void* const /*pTransient*/) const + { std::cout << "proxy1\n"; std::abort(); } + SG::DataProxy* proxy(const CLID& /*id*/) const + { std::cout << "proxy2\n"; std::abort(); } + SG::DataProxy* proxy(const CLID& /*id*/, const std::string& /*key*/) const + { std::cout << "proxy3\n"; std::abort(); } + SG::DataProxy* proxy_exact (SG::sgkey_t /*sgkey*/) const + { std::cout << "proxy_exact1\n"; std::abort(); } + std::vector<const SG::DataProxy*> proxies() const + { std::cout << "proxies\n"; std::abort(); } + StatusCode addToStore (CLID /*id*/, SG::DataProxy* /*proxy*/) + { std::cout << "addToStore\n"; std::abort(); } + + sgkey_t stringToKey (const std::string& /*str*/, CLID /*clid*/) + { std::cout << "stringToKey\n"; std::abort(); } + const std::string* keyToString (sgkey_t /*key*/) const + { std::cout << "keyToString1\n"; std::abort(); } + const std::string* keyToString (sgkey_t /*key*/, CLID& /*clid*/) const + { std::cout << "keyToString2\n"; std::abort(); } + void registerKey (sgkey_t /*key*/, const std::string& /*str*/, CLID /*clid*/) + { std::cout << "registerKey\n"; std::abort(); } +}; + + +void test1() +{ + std::cout << "test1\n"; + TestStore store; + + SG::DataProxy dp; + assert (dp.store() == 0); + dp.setStore (&store); + assert (dp.store() == &store); +} + + +// Test setConst() +void test2() +{ + std::cout << "test2\n"; + + X1* x1 = new X1; + DataObject* b1 = SG::asStorable (x1); + SG::DataProxy dp1; + dp1.setObject (b1); + assert (!dp1.isConst()); + dp1.setConst(); + assert (dp1.isConst()); + + XLock* xlock = new XLock; + DataObject* b2 = SG::asStorable (xlock); + SG::DataProxy dp2; + dp2.setObject (b2); + assert (!dp2.isConst()); + assert (!xlock->m_locked); + dp2.setConst(); + assert (dp2.isConst()); + assert (xlock->m_locked); + + XLock* xlock_a = new XLock; + DataObject* b2a = SG::asStorable (xlock_a); + assert (!xlock_a->m_locked); + dp2.setObject (b2a); + assert (xlock_a->m_locked); + assert (dp2.isConst()); +} + + +int main() +{ + test1(); + test2(); + + // FIXME: INCOMPLETE! + + return 0; +} + + diff --git a/Control/SGTools/test/DataStore_test.cxx b/Control/SGTools/test/DataStore_test.cxx new file mode 100644 index 0000000000000000000000000000000000000000..4a1aa8df79927f8d01ed14f9df6a052bfdf8c58d --- /dev/null +++ b/Control/SGTools/test/DataStore_test.cxx @@ -0,0 +1,573 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// $Id$ +/** + * @file DataStore_test.cxx + * @author scott snyder <snyder@bnl.gov> + * @date Nov, 2013 + * @brief Regression tests for DataStore. + */ + +#undef NDEBUG +#include "SGTools/DataStore.h" +#include "SGTools/StringPool.h" +#include "SGTools/DataProxy.h" +#include "SGTools/TransientAddress.h" +#include "SGTools/IProxyDictWithPool.h" +#include "AthenaKernel/getMessageSvc.h" +#include "AthenaKernel/IAddressProvider.h" +#include <iostream> +#include <cstdlib> +#include <cassert> + + +class TestProvider + : public IAddressProvider +{ +public: + virtual StatusCode updateAddress(StoreID::type /*storeID*/, + SG::TransientAddress* /*pTAd*/) + { return StatusCode::SUCCESS; } +}; + + +class TestPool + : public IProxyDictWithPool +{ +public: + virtual + sgkey_t stringToKey (const std::string& str, CLID clid) + { return m_pool.stringToKey (str, clid); } + virtual + const std::string* keyToString (sgkey_t key) const + { return m_pool.keyToString (key); } + virtual + const std::string* keyToString (sgkey_t key, + CLID& clid) const + { return m_pool.keyToString (key, clid); } + virtual + void registerKey (sgkey_t key, + const std::string& str, + CLID clid) + { m_pool.registerKey (key, str, clid); } + + + virtual unsigned long addRef() { std::abort(); } + virtual unsigned long release() { std::abort(); } + virtual const std::string& name() const { std::abort(); } + virtual StatusCode queryInterface(const InterfaceID &, void** ) { std::abort(); } + virtual SG::DataProxy* proxy(const CLID&) const { std::abort(); } + virtual StatusCode addToStore (CLID , SG::DataProxy*) { std::abort(); } + virtual SG::DataProxy* deep_proxy(const void* const) const { std::abort(); } + virtual SG::DataProxy* proxy(const void* const) const { std::abort(); } + virtual SG::DataProxy* proxy_exact (SG::sgkey_t) const { std::abort(); } + virtual std::vector<const SG::DataProxy*> proxies() const { std::abort(); } + virtual SG::DataProxy* proxy(const CLID&, const std::string&) const { std::abort(); } + + SG::StringPool m_pool; +}; + + +SG::DataProxy* make_proxy (CLID clid, const std::string& name) +{ + SG::TransientAddress* tad = new SG::TransientAddress (clid, name); + return new SG::DataProxy (tad, (IConversionSvc*)0); +} + + +void test_ctor() +{ + std::cout << "test_ctor\n"; + TestPool pool; + SG::DataStore store (pool); + assert (store.storeID() == StoreID::UNKNOWN); + store.setStoreID (StoreID::SPARE_STORE); + assert (store.storeID() == StoreID::SPARE_STORE); +} + + +void test_addToStore() +{ + std::cout << "test_addToStore\n"; + + TestPool pool; + SG::DataStore store (pool); + SG::StringPool::sgkey_t sgkey = pool.stringToKey ("dp1", 123); + + assert (store.addToStore (123, 0).isFailure()); + SG::DataProxy* dp1 = make_proxy (123, "dp1"); + assert (dp1->refCount() == 0); + assert (store.addToStore (123, dp1).isSuccess()); + assert (dp1->store() == &pool); + assert (dp1->refCount() == 1); + assert (dp1->transientAddress()->sgkey() == sgkey); + assert (store.proxy_exact (sgkey) == dp1); + assert (store.proxy (123, "dp1") == dp1); + + int trans1; + dp1->registerTransient (&trans1); + assert (store.locatePersistent (&trans1) == dp1); + + SG::DataProxy* dp2 = make_proxy (123, "dp2"); + assert (store.addToStore (124, dp2).isSuccess()); + SG::StringPool::sgkey_t sgkey2a = pool.stringToKey ("dp2", 123); + SG::StringPool::sgkey_t sgkey2b = pool.stringToKey ("dp2", 124); + assert (store.proxy_exact (sgkey2b) == dp2); + assert (store.proxy_exact (sgkey2a) == 0); + assert (dp2->transientAddress()->sgkey() == sgkey2a); +} + + +void test_addAlias() +{ + std::cout << "test_addAlias\n"; + + TestPool pool; + SG::DataStore store (pool); + + SG::DataProxy* dp1 = make_proxy (123, "dp1"); + assert (store.addToStore (123, dp1).isSuccess()); + + assert (store.addAlias ("dp1a", dp1).isSuccess()); + assert (store.addAlias ("dp1b", dp1).isSuccess()); + assert (dp1->refCount() == 3); + + assert (store.proxy (123, "dp1a") == dp1); + assert (store.proxy_exact (pool.stringToKey ("dp1a", 123)) == dp1); + + assert (dp1->transientAddress()->alias().count ("dp1a") == 1); + + SG::DataProxy* dp2 = make_proxy (123, "dp2"); + assert (store.addToStore (123, dp2).isSuccess()); + assert (store.addAlias ("dpx", dp2).isSuccess()); + assert (dp2->refCount() == 2); + assert (dp2->transientAddress()->alias().count ("dpx") == 1); + + assert (store.addAlias ("dpx", dp1).isSuccess()); + assert (dp1->refCount() == 4); + assert (dp2->refCount() == 1); + assert (dp2->transientAddress()->alias().count ("dpx") == 0); + assert (dp1->transientAddress()->alias().count ("dpx") == 1); + assert (store.addAlias ("dpx", dp1).isSuccess()); + assert (dp1->refCount() == 4); + assert (dp2->refCount() == 1); +} + + +void test_addSymLink() +{ + std::cout << "test_addSymLink\n"; + + TestPool pool; + SG::DataStore store (pool); + + SG::DataProxy* dp1 = make_proxy (123, "dp1"); + assert (store.addToStore (123, dp1).isSuccess()); + assert (store.addSymLink (124, dp1).isSuccess()); + + assert (store.proxy_exact (123, "dp1") == dp1); + assert (store.proxy_exact (124, "dp1") == dp1); + assert (dp1->transientAddress()->transientID(123)); + assert (dp1->transientAddress()->transientID(124)); + + assert (store.addSymLink (124, dp1).isSuccess()); + assert (store.proxy_exact (124, "dp1") == dp1); + + SG::DataProxy* dp2 = make_proxy (125, "dp1"); + assert (store.addToStore (125, dp2).isSuccess()); + assert (store.addSymLink (125, dp1).isFailure()); + assert (!dp1->transientAddress()->transientID(125)); +} + + +void test_proxy_exact() +{ + std::cout << "test_proxy_exact\n"; + + TestPool pool; + SG::DataStore store (pool); + + SG::DataProxy* dp1 = make_proxy (123, "dp1"); + assert (store.addToStore (123, dp1).isSuccess()); + + assert (store.proxy_exact (123, "dp1") == dp1); + assert (store.proxy_exact (124, "dp1") == 0); + assert (store.proxy_exact (123, "dp2") == 0); + SG::StringPool::sgkey_t sgkey = pool.stringToKey ("dp1", 123); + assert (store.proxy_exact (sgkey) == dp1); + assert (store.proxy_exact (sgkey+1) == 0); +} + + +void test_proxy() +{ + std::cout << "test_proxy\n"; + + TestPool pool; + SG::DataStore store (pool); + + SG::DataProxy* dp1 = make_proxy (123, "dp1"); + assert (store.addToStore (123, dp1).isSuccess()); + + assert (store.proxy (123, "dp1") == dp1); + assert (store.proxy (123, "") == dp1); + + assert (store.proxy (new SG::TransientAddress (123, "dp1")) == dp1); + + assert (store.addAlias ("dp1a", dp1).isSuccess()); + assert (store.addAlias ("dp1b", dp1).isSuccess()); + assert (store.proxy (123, "") == dp1); + + SG::DataProxy* dp2 = make_proxy (124, "dp2"); + assert (store.addToStore (123, dp2).isSuccess()); + assert (store.proxy (123, "") == dp1); + + SG::DataProxy* dp3 = make_proxy (123, "dp3"); + assert (store.addToStore (123, dp3).isSuccess()); + assert (store.proxy (123, "") == 0); + assert (store.proxy (123, "dp3") == dp3); +} + + +void test_typeCount() +{ + std::cout << "test_typeCount\n"; + + TestPool pool; + SG::DataStore store (pool); + + SG::DataProxy* dp1 = make_proxy (123, "dp1"); + assert (store.addToStore (123, dp1).isSuccess()); + assert (store.addSymLink (124, dp1).isSuccess()); + + SG::DataProxy* dp2 = make_proxy (123, "dp2"); + assert (store.addToStore (123, dp2).isSuccess()); + + assert (store.typeCount (123) == 2); + assert (store.typeCount (124) == 1); + assert (store.typeCount (125) == 0); +} + + +void test_tRange() +{ + std::cout << "test_tRange\n"; + + TestPool pool; + SG::DataStore store (pool); + + SG::DataProxy* dp1 = make_proxy (123, "dp1"); + assert (store.addToStore (123, dp1).isSuccess()); + assert (store.addSymLink (124, dp1).isSuccess()); + + SG::DataProxy* dp2 = make_proxy (123, "dp2"); + assert (store.addToStore (123, dp2).isSuccess()); + + SG::DataStore::ConstStoreIterator tbeg; + SG::DataStore::ConstStoreIterator tend; + assert (store.tRange (tbeg, tend).isSuccess()); + + assert (tbeg->first == 123); + assert (tbeg->second.size() == 2); + ++tbeg; + assert (tbeg->first == 124); + assert (tbeg->second.size() == 1); + ++tbeg; + assert (tbeg == tend); +} + + +void test_pRange() +{ + std::cout << "test_pRange\n"; + + TestPool pool; + SG::DataStore store (pool); + + SG::DataProxy* dp1 = make_proxy (123, "dp1"); + assert (store.addToStore (123, dp1).isSuccess()); + assert (store.addSymLink (124, dp1).isSuccess()); + + SG::DataProxy* dp2 = make_proxy (123, "dp2"); + assert (store.addToStore (123, dp2).isSuccess()); + + SG::ConstProxyIterator pbeg; + SG::ConstProxyIterator pend; + + assert (store.pRange (123, pbeg, pend).isSuccess()); + assert (pbeg->first == "dp1"); + assert (pbeg->second == dp1); + ++pbeg; + assert (pbeg->first == "dp2"); + assert (pbeg->second == dp2); + ++pbeg; + assert (pbeg == pend); + + assert (store.pRange (124, pbeg, pend).isSuccess()); + assert (pbeg->first == "dp1"); + assert (pbeg->second == dp1); + ++pbeg; + assert (pbeg == pend); + + assert (store.pRange (125, pbeg, pend).isFailure()); + assert (pbeg == pend); +} + + +void test_proxyList() +{ + std::cout << "test_proxyList\n"; + + TestPool pool; + SG::DataStore store (pool); + + SG::DataProxy* dp1 = make_proxy (123, "dp1"); + assert (store.addToStore (123, dp1).isSuccess()); + assert (store.addSymLink (124, dp1).isSuccess()); + + SG::DataProxy* dp2 = make_proxy (123, "dp2"); + assert (store.addToStore (123, dp2).isSuccess()); + + std::list<SG::DataProxy*> pl; + assert (store.proxyList (pl).isSuccess()); + assert (pl.size() == 3); + + std::vector<SG::DataProxy*> pv (pl.begin(), pl.end()); + assert (pv[0] == dp1); + assert (pv[1] == dp2); + assert (pv[2] == dp1); +} + + +void test_keys() +{ + std::cout << "test_keys\n"; + + TestPool pool; + SG::DataStore store (pool); + + SG::DataProxy* dp1 = make_proxy (123, "dp1"); + assert (store.addToStore (123, dp1).isSuccess()); + assert (store.addSymLink (124, dp1).isSuccess()); + + SG::DataProxy* dp2 = make_proxy (123, "dp2"); + assert (store.addToStore (123, dp2).isSuccess()); + + std::vector<std::string> v; + store.keys (123, v, true, false); + assert (v.size() == 2); + assert (v[0] == "dp1"); + assert (v[1] == "dp2"); + + store.keys (124, v, true, false); + assert (v.size() == 1); + assert (v[0] == "dp1"); + + assert (store.addAlias ("dp1a", dp1).isSuccess()); + store.keys (123, v, false, false); + assert (v.size() == 2); + assert (v[0] == "dp1"); + assert (v[1] == "dp2"); + + store.keys (123, v, true, false); + assert (v.size() == 3); + assert (v[0] == "dp1"); + assert (v[1] == "dp1a"); + assert (v[2] == "dp2"); + + SG::DataProxy* dp3 = make_proxy (125, "dp3"); + SG::DataProxy* dp4 = make_proxy (125, "dp4"); + assert (store.addToStore (125, dp3).isSuccess()); + assert (store.addToStore (125, dp4).isSuccess()); + TestProvider prov; + dp4->transientAddress()->setProvider (&prov, StoreID::SPARE_STORE); + + store.keys (125, v, true, false); + assert (v.size() == 2); + assert (v[0] == "dp3"); + assert (v[1] == "dp4"); + + store.keys (125, v, true, true); + assert (v.size() == 1); + assert (v[0] == "dp4"); +} + + +void test_removeProxy() +{ + std::cout << "test_removeProxy\n"; + + TestPool pool; + SG::DataStore store (pool); + + assert (store.removeProxy (0, false).isFailure()); + + SG::DataProxy* dp1 = make_proxy (123, "dp1"); + dp1->addRef(); + assert (store.addToStore (123, dp1).isSuccess()); + assert (store.addSymLink (124, dp1).isSuccess()); + assert (store.addAlias ("dp1x", dp1).isSuccess()); + + assert (store.proxy_exact (pool.stringToKey ("dp1", 123)) == dp1); + assert (store.proxy_exact (pool.stringToKey ("dp1", 124)) == dp1); + assert (store.proxy_exact (pool.stringToKey ("dp1x", 123)) == dp1); + assert (store.proxy (123, "dp1") == dp1); + assert (store.proxy (124, "dp1") == dp1); + assert (store.proxy (123, "dp1x") == dp1); + + assert (dp1->refCount() == 4); + + dp1->resetOnly (true); + assert (store.removeProxy (dp1, false).isSuccess()); + assert (dp1->refCount() == 4); + + dp1->resetOnly (false); + assert (store.removeProxy (dp1, false).isSuccess()); + assert (dp1->refCount() == 1); + assert (store.proxy_exact (pool.stringToKey ("dp1", 123)) == 0); + assert (store.proxy_exact (pool.stringToKey ("dp1", 124)) == 0); + assert (store.proxy_exact (pool.stringToKey ("dp1x", 123)) == 0); + assert (store.proxy (123, "dp1") == 0); + assert (store.proxy (124, "dp1") == 0); + assert (store.proxy (123, "dp1x") == 0); + +} + + +void test_clearStore() +{ + std::cout << "test_clearStore\n"; + + TestPool pool; + SG::DataStore store (pool); + + SG::DataProxy* dp1 = make_proxy (123, "dp1"); + DataObject* o1 = new DataObject; + dp1->setObject (o1); + dp1->addRef(); + assert (store.addToStore (123, dp1).isSuccess()); + assert (store.addSymLink (124, dp1).isSuccess()); + dp1->resetOnly (false); + + SG::DataProxy* dp2 = make_proxy (123, "dp2"); + assert (store.addToStore (123, dp2).isSuccess()); + DataObject* o2 = new DataObject; + dp2->setObject (o2); + dp2->addRef(); + + assert (dp1->refCount() == 3); + assert (dp2->refCount() == 2); + + int trans1; + dp1->registerTransient (&trans1); + assert (store.locatePersistent (&trans1) == dp1); + int trans2; + dp2->registerTransient (&trans2); + assert (store.locatePersistent (&trans2) == dp2); + + store.clearStore(); + + assert (store.locatePersistent (&trans1) == 0); + assert (store.locatePersistent (&trans2) == 0); + + assert (dp1->refCount() == 1); + assert (dp1->object() == o1); + assert (store.proxy (123, "dp1") == 0); + assert (store.proxy (124, "dp1") == 0); + assert (store.proxy_exact (pool.stringToKey ("dp1", 123)) == 0); + assert (store.proxy_exact (pool.stringToKey ("dp1", 124)) == 0); + + assert (dp2->refCount() == 2); + assert (dp2->object() == 0); + assert (store.proxy (123, "dp2") == dp2); + assert (store.proxy_exact (pool.stringToKey ("dp2", 123)) == dp2); + + store.clearStore(true); + assert (dp2->refCount() == 1); + assert (store.proxy (123, "dp2") == 0); + assert (store.proxy_exact (pool.stringToKey ("dp2", 123)) == 0); +} + + +void test_t2p() +{ + std::cout << "test_t2p\n"; + + TestPool pool; + SG::DataStore store (pool); + + SG::DataProxy* dp1 = make_proxy (123, "dp1"); + assert (store.addToStore (123, dp1).isSuccess()); + + int trans1; + assert (store.locatePersistent (&trans1) == 0); + assert (store.t2pRegister (&trans1, dp1).isSuccess()); + assert (store.locatePersistent (&trans1) == dp1); + assert (store.locatePersistent (&trans1) == dp1); + assert (store.t2pRegister (&trans1, dp1).isFailure()); + store.t2pRemove (&trans1); + assert (store.locatePersistent (&trans1) == 0); +} + + +void test_dummy() +{ + std::cout << "test_dummy\n"; + + TestPool pool; + SG::DataStore store (pool); + + SG::StringPool::sgkey_t sgkey = pool.stringToKey ("dp1", 456); + + SG::DataProxy* dp1 = make_proxy (0, ""); + dp1->transientAddress()->setSGKey (sgkey); + assert (store.addToStore (0, dp1).isSuccess()); + assert (dp1->refCount() == 1); + assert (store.proxy_exact (sgkey) == dp1); + + assert (store.proxy (456, "dp1") == dp1); + assert (dp1->clID() == 456); + assert (dp1->name() == "dp1"); + assert (dp1->refCount() == 1); + + SG::StringPool::sgkey_t sgkey2 = pool.stringToKey ("dp2", 456); + SG::DataProxy* dp2 = make_proxy (0, ""); + dp2->transientAddress()->setSGKey (sgkey2); + assert (store.addToStore (0, dp2).isSuccess()); + assert (dp2->refCount() == 1); + assert (store.proxy_exact (sgkey2) == dp2); + + assert (store.proxy (456, "dp2") == dp2); + assert (dp2->clID() == 456); + assert (dp2->name() == "dp2"); + assert (dp2->refCount() == 1); +} + + +int main() +{ + Athena::getMessageSvcQuiet = true; + test_ctor(); + test_addToStore(); + test_addAlias(); + test_addSymLink(); + test_proxy_exact(); + test_proxy(); + test_typeCount(); + test_tRange(); + test_pRange(); + test_proxyList(); + test_keys(); + test_removeProxy(); + test_clearStore(); + test_t2p(); + // pac routines not tested. + test_dummy(); + return 0; +} + + +// handle retrieval of dummied dp +// insert dummied dp diff --git a/Control/SGTools/test/SGTools.xml b/Control/SGTools/test/SGTools.xml new file mode 100755 index 0000000000000000000000000000000000000000..cf2d08d1d457c5a83d86225f56d2f7b7a7af6c40 --- /dev/null +++ b/Control/SGTools/test/SGTools.xml @@ -0,0 +1,16 @@ +<?xml version="1.0"?> +<atn> + <TEST name="SGToolsTest" type="makecheck" suite="Examples"> + <package>Control/SGTools</package> + <timelimit>10</timelimit> + <author> Paolo Calafiura </author> + <mailto> pcalafiura@lbl.gov</mailto> + <expectations> + <errorMessage>Athena exited abnormally</errorMessage> + <errorMessage>differ</errorMessage> + <warningMessage> # WARNING_MESSAGE : post.sh> ERROR</warningMessage> + <successMessage>check ok</successMessage> + <returnValue>0</returnValue> + </expectations> + </TEST> +</atn> diff --git a/Control/SGTools/test/StringPool_test.cxx b/Control/SGTools/test/StringPool_test.cxx new file mode 100755 index 0000000000000000000000000000000000000000..796666ba91ac9a8348e603c31d1529f51192b9b1 --- /dev/null +++ b/Control/SGTools/test/StringPool_test.cxx @@ -0,0 +1,105 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// $Id: StringPool_test.cxx,v 1.2 2007-12-10 22:20:04 ssnyder Exp $ +/** + * @file SGTools/StringPool_test.cxx + * @author scott snyder + * @date Mar 2007 + * @brief Regression test for StringPool. + */ + + +#undef NDEBUG + +#include "SGTools/StringPool.h" +#include "SGTools/crc64.h" +#include <vector> +#include <string> +#include <cstdlib> +#include <cassert> +#include <iostream> + + +const char* teststrings[] = { + "", + "MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGTVIRGATTSYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE", + "MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGDVIRGATTHYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE", + "ajsdla lkjasd lkjasd ", + "paks aspdk pok asd", + "asd laskjkd lkajsd", +}; + + +std::string randstring() +{ + char buf[256]; + int len = std::rand() % 256; + for (int i = 0; i < len; i++) + buf[i] = (char)(std::rand() % 256); + return std::string (buf, len); +} + + +void test1() +{ + SG::StringPool sp; + std::vector<std::string> strings; + std::vector<SG::StringPool::sgkey_t> keys; + std::vector<SG::StringPool::sgaux_t> aux; + int ntest = sizeof (teststrings) / sizeof (teststrings[0]); + for (int i = 0; i < ntest; i++) { + SG::StringPool::sgkey_t key = sp.stringToKey (teststrings[i], i); + assert (key <= SG::StringPool::sgkey_t_max); + strings.push_back (teststrings[i]); + keys.push_back (key); + aux.push_back (i); + std::cout << SG::crc64format (key) << " " << teststrings[i] << "\n"; + } + + std::cout << "pool dump\n"; + sp.dump(); + + for (int i=0; i < 1000; i++) { + SG::StringPool::sgaux_t auxkey = std::rand(); + std::string str = randstring(); + SG::StringPool::sgkey_t key = sp.stringToKey (str, auxkey); + assert (key <= SG::StringPool::sgkey_t_max); + strings.push_back (str); + keys.push_back (key); + aux.push_back (auxkey); + } + + for (size_t i = 0; i < keys.size(); i++) { + SG::StringPool::sgaux_t auxout; + assert (*sp.keyToString (keys[i]) == strings[i]); + assert (*sp.keyToString (keys[i], auxout) == strings[i]); + assert (auxout == aux[i]); + assert (!sp.keyToString (keys[i]+1)); + } + + for (size_t i = 0; i < keys.size(); i++) { + assert (sp.registerKey (keys[i]+1, strings[i], aux[i])); + } + + for (size_t i = 0; i < keys.size(); i++) { + SG::StringPool::sgaux_t auxout = 0; + assert (*sp.keyToString (keys[i], auxout) == strings[i]); + assert (auxout == aux[i]); + auxout = 0; + assert (*sp.keyToString (keys[i]+1, auxout) == strings[i]); + assert (auxout == aux[i]); + } + + assert (sp.registerKey (keys[10], strings[10], aux[10])); + assert (!sp.registerKey (keys[10], strings[11], aux[10])); + assert (!sp.registerKey (keys[10], strings[10], aux[11])); +} + + +int main() +{ + test1(); + return 0; +} diff --git a/Control/SGTools/test/TransientAddress_test.cxx b/Control/SGTools/test/TransientAddress_test.cxx new file mode 100644 index 0000000000000000000000000000000000000000..3a58bbb610477ebdf37beaad415af2af906093ed --- /dev/null +++ b/Control/SGTools/test/TransientAddress_test.cxx @@ -0,0 +1,181 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// $Id$ +/** + * @file TransientAddress_test.cxx + * @author scott snyder <snyder@bnl.gov> + * @date Nov, 2013 + * @brief Regression tests for TransientAddress. + */ + +#undef NDEBUG +#include "SGTools/TransientAddress.h" +#include "AthenaKernel/IAddressProvider.h" +#include "GaudiKernel/IOpaqueAddress.h" +#include <iostream> +#include <cstdlib> +#include <cassert> + + +class TestAddress + : public IOpaqueAddress +{ +public: + TestAddress (int x) : m_x (x), m_ref(0) {} + /// Add reference to object + virtual unsigned long addRef (); + /// release reference to object + virtual unsigned long release (); + /// Retrieve class information from link + virtual const CLID& clID () const { std::abort(); } + /// Retrieve service type + virtual long svcType () const { std::abort(); } + /// Update branch name + virtual IRegistry* registry () const { std::abort(); } + /// Update directory pointer + virtual void setRegistry(IRegistry* /*r*/) { std::abort(); } + /// Retrieve String parameters + virtual const std::string* par () const { std::abort(); } + /// Access to generic link parameters + virtual const unsigned long* ipar () const { std::abort(); } + + int m_x; + int m_ref; +}; + + +class TestProvider + : public IAddressProvider +{ +public: + virtual StatusCode updateAddress(StoreID::type /*storeID*/, + SG::TransientAddress* /*pTAd*/) + { return StatusCode::SUCCESS; } +}; + + +unsigned long TestAddress::addRef() +{ + ++m_ref; + std::cout << "addRef " << m_x << " " << m_ref << "\n"; + return m_ref; +} + + +unsigned long TestAddress::release() +{ + --m_ref; + std::cout << "release " << m_x << " " << m_ref << "\n"; + return m_ref; +} + + +void test1() +{ + std::cout << "test1\n"; + + SG::TransientAddress tad1; + assert (tad1.clID() == CLID_NULL); + assert (tad1.name() == ""); + assert (tad1.transientID().size() == 0); + assert (tad1.alias().size() == 0); + assert (!tad1.isValid()); + assert (tad1.provider() == 0); + assert (tad1.storeID() == StoreID::UNKNOWN); + assert (tad1.address() == 0); + assert (tad1.sgkey() == 0); + tad1.setID (123, "key"); + assert (tad1.name() == "key"); + assert (tad1.clID() == 123); + assert (tad1.transientID().size() == 1); + assert (tad1.alias().size() == 0); + + SG::TransientAddress tad2 (123, "key"); + assert (tad2.name() == "key"); + assert (tad2.clID() == 123); + assert (tad2.transientID().size() == 1); + assert (tad2.alias().size() == 0); + assert (!tad2.isValid()); + assert (tad2.provider() == 0); + assert (tad2.storeID() == StoreID::UNKNOWN); + assert (tad2.address() == 0); + assert (tad2.sgkey() == 0); + + tad2.setSGKey (876); + assert (tad2.sgkey() == 876); + + assert (tad2.transientID (123)); + assert (!tad2.transientID (124)); + tad2.setTransientID (124); + assert (tad2.transientID (124)); + assert (tad2.transientID().size() == 2); + + tad2.setAlias ("key2"); + assert (tad2.alias().size() == 1); + std::set<std::string> a; + a.insert ("key3"); + a.insert ("key4"); + tad2.setAlias (a); + assert (tad2.alias().size() == 2); + assert (tad2.alias().count ("key2") == 0); + assert (tad2.alias().count ("key3") == 1); + tad2.removeAlias ("key3"); + assert (tad2.alias().size() == 1); + assert (tad2.alias().count ("key3") == 0); + + TestAddress ad1(1); + SG::TransientAddress tad3 (123, "key", &ad1); + assert (tad3.name() == "key"); + assert (tad3.clID() == 123); + assert (tad3.isValid()); + assert (tad3.provider() == 0); + assert (tad3.storeID() == StoreID::UNKNOWN); + assert (tad3.address() == &ad1); + + TestAddress ad2(2); + tad3.setAddress (&ad2); + assert (tad3.isValid()); + assert (tad3.address() == &ad2); + tad3.reset(); + assert (!tad3.isValid()); + assert (tad3.address() == 0); + + tad3.setAddress (&ad2); + tad3.clearAddress (false); + tad3.reset(); + assert (tad3.isValid()); + assert (tad3.address() == &ad2); + tad3.clearAddress (true); + tad3.reset(); + assert (!tad3.isValid()); + assert (tad3.address() == 0); + + TestProvider tp; + tad3.setProvider (&tp, StoreID::SPARE_STORE); + assert (tad3.provider() == &tp); + assert (tad3.storeID() == StoreID::SPARE_STORE); + assert (tad3.isValid()); + tad3.consultProvider (false); + assert (!tad3.isValid()); + tad3.consultProvider (true); + assert (tad3.isValid()); + + SG::TransientAddress tad4(0, ""); + assert (tad4.clID() == CLID_NULL); + assert (tad4.name() == ""); + assert (tad4.transientID().size() == 0); + tad4.setID (123, "key"); + assert (tad4.name() == "key"); + assert (tad4.clID() == 123); + assert (tad4.transientID().size() == 1); + assert (tad4.alias().size() == 0); +} + + +int main() +{ + test1(); + return 0; +} diff --git a/Control/SGTools/test/VersionedKey_test.cxx b/Control/SGTools/test/VersionedKey_test.cxx new file mode 100644 index 0000000000000000000000000000000000000000..b5fb7fd162bbb8a3390adddccba04ad2a8676e02 --- /dev/null +++ b/Control/SGTools/test/VersionedKey_test.cxx @@ -0,0 +1,78 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#undef NDEBUG + +#include "SGTools/SGVersionedKey.h" +#include <cstring> +#include <iostream> +#include <stdexcept> +#include <string> +using namespace std; +using namespace SG; + +#include <cassert> +#define SGASSERTERROR( FALSEEXPR ) \ + std::cerr << "Now we expect to see an error message:" << std::endl \ + << "----Error Message Starts--->>" << std::endl; \ + assert(!FALSEEXPR); \ + std::cerr<< "<<---Error Message Ends-------" << std::endl + +int main() { + VersionedKey vk1("bla", 1); + std::string key("Bleah"); + unsigned int version(99); + VersionedKey vk2(key, version); + VersionedKey vk3(";00;default"); + VersionedKey vk4("default"); + + cout << "Versioned Key 1=" << vk1 << endl; + char* k1(0); + unsigned char v1(0); + vk1.decode(k1,v1); + assert(0 == strcmp("bla",k1)); + assert(1 == v1); + cout << "Versioned Key 2=" << vk2 << endl; + vk2.decode(k1,v1); + assert(0 == strcmp("Bleah",k1)); + assert(99 == v1); + assert(99 == vk2.version()); + cout << "Versioned Key 3=" << vk3 << endl; + vk3.decode(k1,v1); + assert(0 == strcmp("default",k1)); + assert(0 == v1); + vk4.decode(k1,v1); + assert(0 == strcmp("default",k1)); + assert(0 == v1); + + assert(0 == strcmp("bla", vk1.key())); + assert(0 == strcmp("Bleah", vk2.key())); + assert(0 == strcmp("default",vk3.key())); + + + //compare vkeys + VersionedKey ck1("bla", 1); + VersionedKey ck2("bla", 2); + VersionedKey ck3("blu", 0); + VersionedKey ck4("blu", 0); + assert(ck1 < ck2); + assert(!(ck2 < ck1)); + assert(ck1 < ck3); + assert(!(ck3 < ck1)); + assert(ck2 < ck3); + assert(!(ck3 < ck1)); + assert(!(ck3 < ck4)); + assert(!(ck4 < ck3)); + + assert(!ck1.sameKey(ck4)); + assert(ck3.sameKey(ck4)); + assert(ck3.sameKey("blu")); + std::string bluString("blu"); + assert(ck3.sameKey(bluString)); + + return 0; +} + + + diff --git a/Control/SGTools/test/crc64_test.cxx b/Control/SGTools/test/crc64_test.cxx new file mode 100755 index 0000000000000000000000000000000000000000..b97ad615c93f8498b5152656b67da4b2869d9727 --- /dev/null +++ b/Control/SGTools/test/crc64_test.cxx @@ -0,0 +1,48 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// $Id: crc64_test.cxx,v 1.2 2007-03-08 02:02:06 ssnyder Exp $ +/** + * @file SGTools/crc64_test.cxx + * @author scott snyder, originally from David T. Jones + * @date Mar 2007 + * @brief Regression tests for CRC-64 calculation. + */ + +#undef NDEBUG + +#include "SGTools/crc64.h" +#include <iostream> +#include <cassert> + + +void testextend (const std::string& str, unsigned int x) +{ + uint64_t crc1 = SG::crc64 (str); + crc1 = SG::crc64addint (crc1, x); + + std::string str2 = str; + while (x > 0) { + str2.push_back ((char)(x&0xff)); + x >>= 8; + } + assert (crc1 == SG::crc64 (str2)); +} + + +int main() +{ + const char* testin1 = "MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGTVIRGATTSYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE"; + const char* testout1 = "C874767DA8254746"; + const char* testin2 = "MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGDVIRGATTHYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE"; /* Differs from 1st seq in two places */ + const char* testout2 = "2DF1AA17420FCA3F"; + + assert (SG::crc64digest (testin1) == std::string (testout1)); + assert (SG::crc64digest (testin2) == std::string (testout2)); + + testextend (testin1, 54356); + testextend (testin2, 9812674); + return 0; +} + diff --git a/Control/SGTools/test/exceptions_test.cxx b/Control/SGTools/test/exceptions_test.cxx new file mode 100644 index 0000000000000000000000000000000000000000..aacbba6b705f67c26ae23d740d47a8c50a929d85 --- /dev/null +++ b/Control/SGTools/test/exceptions_test.cxx @@ -0,0 +1,32 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +// $Id$ +/** + * @file SGTools/test/exceptions_test.cxx + * @author scott snyder <snyder@bnl.gov> + * @date Feb, 2014 + * @brief Regression tests for exceptions. + */ + +#undef NDEBUG +#include "SGTools/exceptions.h" +#include <iostream> + + +void test1() +{ + std::cout << "test1\n"; + + std::cout << SG::ExcBadDataProxyCast (123, typeid(int)).what() << "\n"; + + std::cout << SG::ExcProxyCollision (123, "abc", 456, "def").what() << "\n"; +} + + +int main() +{ + test1(); + return 0; +} diff --git a/Control/SGTools/test/safe_clid_test.cxx b/Control/SGTools/test/safe_clid_test.cxx new file mode 100755 index 0000000000000000000000000000000000000000..c5a042c6e9c642e8a169dd831852150bfb0833f0 --- /dev/null +++ b/Control/SGTools/test/safe_clid_test.cxx @@ -0,0 +1,31 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#undef NDEBUG + +#include "SGTools/safe_clid.h" +#include "SGTools/CLASS_DEF.h" +#include "GaudiKernel/DataObject.h" +#include <cassert> + +#include <iostream> + +struct A {}; +struct B {}; +CLASS_DEF (B, 98765, 0) +struct C + : public DataObject +{ + static CLID& classID() { static CLID clid = 44444; return clid; } +}; + +int main() +{ + assert (SG::safe_clid<int> () == 0); + assert (SG::safe_clid<A> () == 0); + assert (SG::safe_clid<B> () == 98765); + assert (SG::safe_clid<C> () == 44444); + return 0; +} +