Program Listing for File Referenced.h

Return to documentation for file (include/crpropa/Referenced.h)

#ifndef CRPROPA_REFERENCED_H
#define CRPROPA_REFERENCED_H

#include <cstddef>

#ifdef DEBUG
#include <iostream>
#include <typeinfo>
#endif

namespace crpropa {
class Referenced {
public:

        inline Referenced() :
                        _referenceCount(0) {
        }

        inline Referenced(const Referenced&) :
                        _referenceCount(0) {
        }

        inline Referenced& operator =(const Referenced&) {
                return *this;
        }

        inline size_t addReference() const {
                int newRef;
#if defined(OPENMP_3_1)
                #pragma omp atomic capture
                {newRef = _referenceCount++;}
#elif defined(__GNUC__)
                newRef = __sync_add_and_fetch(&_referenceCount, 1);
#else
                #pragma omp critical
                {newRef = _referenceCount++;}
#endif
                return newRef;
        }

        inline size_t removeReference() const {
#ifdef DEBUG
                if (_referenceCount == 0)
                        std::cerr
                                        << "WARNING: Remove reference from Object with NO references: "
                                        << typeid(*this).name() << std::endl;
#endif
                int newRef;
#if defined(OPENMP_3_1)
                #pragma omp atomic capture
                {newRef = _referenceCount--;}
#elif defined(__GNUC__)
                newRef = __sync_sub_and_fetch(&_referenceCount, 1);
#else
                #pragma omp critical
                {newRef = _referenceCount--;}
#endif

                if (newRef == 0) {
                        delete this;
                }
                return newRef;
        }

        int removeReferenceNoDelete() const {
                return --_referenceCount;
        }

        inline size_t getReferenceCount() const {
                return _referenceCount;
        }

protected:

        virtual inline ~Referenced() {
#ifdef DEBUG
                if (_referenceCount)
                        std::cerr << "WARNING: Deleting Object with references: "
                                        << typeid(*this).name() << std::endl;
#endif
        }

        mutable size_t _referenceCount;
};

inline void intrusive_ptr_add_ref(Referenced* p) {
        p->addReference();
}
inline void intrusive_ptr_release(Referenced* p) {
        p->removeReference();
}

template<class T>
class ref_ptr {
public:
        typedef T element_type;

        ref_ptr() :
                        _ptr(0) {
        }
        ref_ptr(T* ptr) :
                        _ptr(ptr) {
                if (_ptr)
                        _ptr->addReference();
        }
        ref_ptr(const ref_ptr& rp) :
                        _ptr(rp._ptr) {
                if (_ptr)
                        _ptr->addReference();
        }
        template<class Other> ref_ptr(const ref_ptr<Other>& rp) :
                        _ptr(rp._ptr) {
                if (_ptr)
                        _ptr->addReference();
        }

        ~ref_ptr() {
                if (_ptr)
                        _ptr->removeReference();
                _ptr = 0;
        }

        ref_ptr& operator =(const ref_ptr& rp) {
                assign(rp);
                return *this;
        }

        template<class Other> ref_ptr& operator =(const ref_ptr<Other>& rp) {
                assign(rp);
                return *this;
        }

        inline ref_ptr& operator =(T* ptr) {
                if (_ptr == ptr)
                        return *this;
                T* tmp_ptr = _ptr;
                _ptr = ptr;
                if (_ptr)
                        _ptr->addReference();
                if (tmp_ptr)
                        tmp_ptr->removeReference();
                return *this;
        }

        operator T*() const {
                return _ptr;
        }

        T& operator*() const {
                return *_ptr;
        }
        T* operator->() const {
                return _ptr;
        }
        T* get() const {
                return _ptr;
        }

        bool operator!() const {
                return _ptr == 0;
        } // not required
        bool valid() const {
                return _ptr != 0;
        }

        T* release() {
                T* tmp = _ptr;
                if (_ptr)
                        _ptr->removeReferenceNoDelete();
                _ptr = 0;
                return tmp;
        }

        void swap(ref_ptr& rp) {
                T* tmp = _ptr;
                _ptr = rp._ptr;
                rp._ptr = tmp;
        }

private:

        template<class Other> void assign(const ref_ptr<Other>& rp) {
                if (_ptr == rp._ptr)
                        return;
                T* tmp_ptr = _ptr;
                _ptr = rp._ptr;
                if (_ptr)
                        _ptr->addReference();
                if (tmp_ptr)
                        tmp_ptr->removeReference();
        }

        template<class Other> friend class ref_ptr;

        T* _ptr;
};

template<class T> inline
void swap(ref_ptr<T>& rp1, ref_ptr<T>& rp2) {
        rp1.swap(rp2);
}

template<class T> inline T* get_pointer(const ref_ptr<T>& rp) {
        return rp.get();
}

template<class T, class Y> inline ref_ptr<T> static_pointer_cast(
                const ref_ptr<Y>& rp) {
        return static_cast<T*>(rp.get());
}

template<class T, class Y> inline ref_ptr<T> dynamic_pointer_cast(
                const ref_ptr<Y>& rp) {
        return dynamic_cast<T*>(rp.get());
}

template<class T, class Y> inline ref_ptr<T> const_pointer_cast(
                const ref_ptr<Y>& rp) {
        return const_cast<T*>(rp.get());
}

} // namespace crpropa

#endif // CRPROPA_REFERENCED_H