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>
#include <type_traits>
#ifdef DEBUG
#include <iostream>
#include <typeinfo>
#endif
namespace crpropa {
class Referenced {
public:
constexpr Referenced() noexcept :
_referenceCount(0) {
}
constexpr Referenced(const Referenced&) noexcept :
_referenceCount(0) {
}
constexpr Referenced& operator =(const Referenced&) noexcept {
return *this;
}
inline size_t addReference() const noexcept {
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)
{newRef = _referenceCount++;}
#endif
return newRef;
}
#ifdef DEBUG
inline size_t removeReference() const {
if (_referenceCount == 0)
std::cerr
<< "WARNING: Remove reference from Object with NO references: "
<< typeid(*this).name() << std::endl;
#else
inline size_t removeReference() const noexcept {
#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)
{newRef = _referenceCount--;}
#endif
if (newRef == 0) {
delete this;
}
return newRef;
}
inline int removeReferenceNoDelete() const noexcept {
return --_referenceCount;
}
inline size_t getReferenceCount() const noexcept {
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();
}
// helper Reference class functions, which function to use is decided at compile time!
template<class T>
typename std::enable_if_t<std::is_base_of<Referenced, T>::value>
inline addReferenceIf(T* ptr) noexcept {
if (ptr) ptr->addReference();
}
template<class T>
typename std::enable_if_t<!std::is_base_of<Referenced, T>::value>
inline addReferenceIf(T* ptr) noexcept {}
template<class T>
typename std::enable_if_t<std::is_base_of<Referenced, T>::value>
inline removeReferenceIf(T* ptr) noexcept {
if (ptr) ptr->removeReference();
}
template<class T>
typename std::enable_if_t<!std::is_base_of<Referenced, T>::value>
inline removeReferenceIf(T* ptr) noexcept {}
template<class T>
typename std::enable_if_t<std::is_base_of<Referenced, T>::value>
inline removeReferenceNoDeleteIf(T* ptr) noexcept {
if (ptr) ptr->removeReferenceNoDelete();
}
template<class T>
typename std::enable_if_t<!std::is_base_of<Referenced, T>::value>
inline removeReferenceNoDeleteIf(T* ptr) noexcept {}
template<class T>
class ref_ptr {
public:
typedef T element_type;
constexpr ref_ptr() noexcept : _ptr(0) {}
#ifndef SWIG
inline ref_ptr(T& ref) noexcept : _ptr(&ref) {}
#endif
inline ref_ptr(T* ptr) noexcept : _ptr(ptr) {
addReferenceIf(_ptr);
}
inline ref_ptr(const ref_ptr& rp) noexcept : _ptr(rp._ptr) {
addReferenceIf(_ptr);
}
template<class Other> inline ref_ptr(const ref_ptr<Other>& rp) noexcept : _ptr(rp._ptr) {
addReferenceIf(_ptr);
}
inline ~ref_ptr() noexcept {
removeReferenceIf(_ptr);
_ptr = 0;
}
inline ref_ptr& operator =(const ref_ptr& rp) noexcept {
assign(rp);
return *this;
}
template<class Other> inline ref_ptr& operator =(const ref_ptr<Other>& rp) noexcept {
assign(rp);
return *this;
}
inline ref_ptr& operator =(T* ptr) noexcept {
if (_ptr != ptr) {
T* tmp_ptr = _ptr;
_ptr = ptr;
addReferenceIf(_ptr);
removeReferenceIf(tmp_ptr);
}
return *this;
}
#ifndef SWIG
inline ref_ptr& operator =(T& ref) noexcept {
if (_ptr != &ref)
_ptr = &ref;
return *this;
}
#endif
inline operator T*() const noexcept {
return _ptr;
}
inline T& operator*() const noexcept {
return *_ptr;
}
inline T* operator->() const noexcept {
return _ptr;
}
inline T* get() const {
return _ptr;
}
inline bool operator!() const noexcept {
return _ptr == 0;
} // not required
inline bool valid() const noexcept {
return _ptr != 0;
}
inline T* release() noexcept {
T* tmp = _ptr;
removeReferenceNoDeleteIf(_ptr);
_ptr = 0;
return tmp;
}
inline void swap(ref_ptr& rp) noexcept {
T* tmp = _ptr;
_ptr = rp._ptr;
rp._ptr = tmp;
}
private:
template<class Other> inline void assign(const ref_ptr<Other>& rp) noexcept {
if (_ptr != rp._ptr) {
T* tmp_ptr = _ptr;
_ptr = rp._ptr;
addReferenceIf(_ptr);
removeReferenceIf(tmp_ptr);
}
}
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