/* * Copyright information and license terms for this software can be * found in the file LICENSE that is included with the distribution */ /** * @author Michael Davidsaver */ #ifndef SHAREDPTR_H #define SHAREDPTR_H #include /* for auto_ptr */ /** @file sharedPtr.h * Pulls in the std::tr1 namespace with the following names * * class shared_ptr * class weak_ptr * class bad_weak_ptr * function static_pointer_cast; * function dynamic_pointer_cast * function const_pointer_cast * function swap * function get_deleter * function enable_shared_from_this */ /* where should we look? (In decending order of preference) * * # manual (per source file) selection * # c++11 version of , then alias into tr1 * # * # boost version of tr1/memory */ /* Debugging shared_ptr with debugPtr.h requires >= c++11 * * Define DEBUG_SHARED_PTR globally to cause epics::debug::shared_ptr * to be injected as std::tr1::shared_ptr and the macro * HAVE_SHOW_REFS will be defined. * * epics::debug::shared_ptr wraps std::shared_ptr with additional * tracking of backwards references. * std::shared_ptr::use_count() gives the number of shared_ptr * (strong refs) to the referenced object. * * If use_count()==5 then epics::debug::shared_ptr::show_refs() will print * 5 lines of the format * * # : ... * * Given the numberic address of each shared_ptr as well as the call stack * at the point where it was initialized. * Use the 'addr2line' utility to interpret the stack addresses. * * On linux w/ ASLR it is necessary to turn on static linking to meaningfully * interpret call stack addresses. * Append "STATIC_BUILD=YES" to configure/CONFIG_SITE */ //#define DEBUG_SHARED_PTR #if defined(SHARED_FROM_MANUAL) // define SHARED_FROM_MANUAL if from some reason it is desirable to manually select // which shared_ptr implementation to use #elif __cplusplus>=201103L || (defined(_MSC_VER) && (_MSC_VER>=1600)) || (__clang__ && __APPLE__) // c++11 or MSVC 2010 // clang on linux has tr1/memory, clang on OSX doesn't # define SHARED_FROM_STD #elif defined(__GNUC__) && __GNUC__>=4 && !defined(vxWorks) // GCC >=4.0.0 # define SHARED_FROM_TR1 #elif defined(_MSC_VER) && (_MSC_VER>1500 || defined(_HAS_TR1)) // MSVC > 2008, or 2008 w/ SP1 # define SHARED_FROM_TR1 #else # define SHARED_FROM_BOOST #endif // go and get it #if defined(SHARED_FROM_MANUAL) // no-op #elif defined(SHARED_FROM_STD) #include #ifndef DEBUG_SHARED_PTR namespace std { namespace tr1 { using ::std::shared_ptr; using ::std::weak_ptr; using ::std::static_pointer_cast; using ::std::dynamic_pointer_cast; using ::std::const_pointer_cast; using ::std::enable_shared_from_this; using ::std::bad_weak_ptr; } } #else // DEBUG_SHARED_PTR #include "debugPtr.h" namespace std { namespace tr1 { using ::epics::debug::shared_ptr; using ::epics::debug::weak_ptr; using ::epics::debug::static_pointer_cast; using ::epics::debug::dynamic_pointer_cast; using ::epics::debug::const_pointer_cast; using ::epics::debug::enable_shared_from_this; using ::std::bad_weak_ptr; } } #endif // DEBUG_SHARED_PTR #elif defined(SHARED_FROM_TR1) # include #elif defined(SHARED_FROM_BOOST) #if defined(__GNUC__) && __GNUC__ < 3 #define BOOST_EXCEPTION_DISABLE #define BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION #endif # include #else # error No shared_ptr selection #endif // cleanup #ifdef SHARED_FROM_STD # undef SHARED_FROM_STD #endif #ifdef SHARED_FROM_TR1 # undef SHARED_FROM_TR1 #endif #ifdef SHARED_FROM_BOOST # undef SHARED_FROM_BOOST #endif namespace detail { template struct ref_shower { const std::tr1::shared_ptr& ptr; bool self, weak; ref_shower(const std::tr1::shared_ptr& ptr, bool self, bool weak) :ptr(ptr),self(self),weak(weak) {} }; } /** Print a list (one per line) of shared_ptr which refer to the same object * * @param ptr Use the object pointed to by this shared_ptr * @param self include or omit a line for this shared_ptr * @param weak include a line for each weak_ptr (not implemented) @code shared_ptr x; std::cout << show_referrers(x); @endcode */ template inline ::detail::ref_shower show_referrers(const std::tr1::shared_ptr& ptr, bool self=true, bool weak=false) { return ::detail::ref_shower(ptr, self, weak); } namespace std{ template inline std::ostream& operator<<(std::ostream& strm, const ::detail::ref_shower& refs) { #ifdef HAVE_SHOW_REFS refs.ptr.show_refs(strm, refs.self, refs.weak); #endif // HAVE_SHOW_REFS return strm; } }//namespace std #define POINTER_DEFINITIONS(clazz) \ typedef std::tr1::shared_ptr shared_pointer; \ typedef std::tr1::shared_ptr const_shared_pointer; \ typedef std::tr1::weak_ptr weak_pointer; \ typedef std::tr1::weak_ptr const_weak_pointer /* A semi-hack to help with migration from std::auto_ptr to std::unique_ptr, * and avoid copious deprecation warning spam * which may be hiding legitimate issues. * * Provides epics::auto_ptr and epics::swap() * * epics::auto_ptr is std::auto_ptr for c++98 * and std::unique_ptr for >= c++11. * * epics::swap() is the only supported operation. * copy/assignment/return are not supported * (use auto_ptr or unique_ptr explicitly). */ namespace epics{ #if __cplusplus>=201103L template using auto_ptr = std::unique_ptr; template static inline void swap(auto_ptr& lhs, auto_ptr& rhs) { lhs.swap(rhs); } #else using std::auto_ptr; template static inline void swap(auto_ptr& lhs, auto_ptr& rhs) { auto_ptr temp(lhs); lhs = rhs; rhs = temp; } #endif } #endif // SHAREDPTR_H