"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "include/nx_shared_ptr.h" between
netxms-3.8.382.tar.gz and netxms-3.8.405.tar.gz

About: NetXMS is a multi-platform open source network management and monitoring system.

nx_shared_ptr.h  (netxms-3.8.382):nx_shared_ptr.h  (netxms-3.8.405)
skipping to change at line 19 skipping to change at line 19
* Distributed under the MIT License (MIT) (See http://opensource.org/licenses/M IT) * Distributed under the MIT License (MIT) (See http://opensource.org/licenses/M IT)
*/ */
#ifndef _nx_shared_ptr_h_ #ifndef _nx_shared_ptr_h_
#define _nx_shared_ptr_h_ #define _nx_shared_ptr_h_
#include <cstddef> // NULL #include <cstddef> // NULL
#include <algorithm> // std::swap #include <algorithm> // std::swap
#include <nxatomic.h> #include <nxatomic.h>
#if defined(__HP_aCC)
typedef decltype(nullptr) nullptr_t;
#endif
/** /**
* @brief implementation of reference counter for the following minimal smart po inter. * @brief implementation of reference counter for the following minimal smart po inter.
* *
* shared_ptr_count is a container for the allocated pn reference counter. * shared_ptr_count is a container for the allocated pn reference counter.
*/ */
class shared_ptr_count class shared_ptr_count
{ {
public:
shared_ptr_count()
{
refcount = NULL;
}
shared_ptr_count(const shared_ptr_count& count)
{
refcount = count.refcount;
}
/// @brief Swap method for the copy-and-swap idiom (copy constructor and swa
p method)
void swap(shared_ptr_count& lhs)
{
std::swap(refcount, lhs.refcount);
}
/// @brief getter of the underlying reference counter
long use_count(void) const
{
long count = 0;
if (NULL != refcount)
{
count = *refcount;
}
return count;
}
/// @brief acquire/share the ownership of the pointer, initializing the refe
rence counter
template<class U>
void acquire(U* p)
{
if (NULL != p)
{
if (NULL == refcount)
{
refcount = new VolatileCounter(1);
}
else
{
InterlockedIncrement(refcount);
}
}
}
/// @brief release the ownership of the px pointer, destroying the object wh
en appropriate
template<class U>
void release(U* p)
{
if (refcount != NULL)
{
if (InterlockedDecrement(refcount) == 0)
{
delete p;
delete refcount;
}
refcount = NULL;
}
}
private: private:
VolatileCounter *refcount; VolatileCounter useCount;
VolatileCounter weakCount;
VolatileCounter spinLock;
public:
shared_ptr_count()
{
useCount = 0;
weakCount = 0;
spinLock = 0;
}
/// @brief getter of the underlying reference counter
long use_count(void) const
{
return useCount;
}
/// @brief acquire/share the ownership of the pointer, initializing the refer
ence counter
template<class U> void acquire(U *p)
{
if (NULL != p)
{
InterlockedIncrement(&useCount);
InterlockedIncrement(&weakCount);
}
}
/// @brief release the ownership of the px pointer, destroying the object whe
n appropriate
template<class U> void release(U *p)
{
if (InterlockedDecrement(&useCount) == 0)
{
delete p;
if (InterlockedDecrement(&weakCount) == 0)
{
delete this;
}
}
else
{
InterlockedDecrement(&weakCount);
}
}
void weakAcquire()
{
InterlockedIncrement(&weakCount);
}
bool weakLock()
{
while (InterlockedIncrement(&spinLock) != 1)
InterlockedDecrement(&spinLock);
bool success;
if (InterlockedIncrement(&useCount) > 1)
{
InterlockedIncrement(&weakCount);
success = true;
}
else
{
// Use count 1 after increment indicates no more owning shared pointers
InterlockedDecrement(&useCount);
success = false;
}
InterlockedDecrement(&spinLock);
return success;
}
void weakRelease()
{
if (InterlockedDecrement(&weakCount) == 0)
{
delete this;
}
}
}; };
/** /**
* @brief minimal implementation of smart pointer, a subset of the C++11 std::sh ared_ptr or boost::shared_ptr. * @brief minimal implementation of smart pointer, a subset of the C++11 std::sh ared_ptr or boost::shared_ptr.
* *
* shared_ptr is a smart pointer retaining ownership of an object through a prov ided pointer, * shared_ptr is a smart pointer retaining ownership of an object through a prov ided pointer,
* and sharing this ownership with a reference counter. * and sharing this ownership with a reference counter.
* It destroys the object when the last shared pointer pointing to it is destroy ed or reset. * It destroys the object when the last shared pointer pointing to it is destroy ed or reset.
*/ */
template<class T> template<class T> class shared_ptr
class shared_ptr
{ {
// This allow pointer_cast functions to share the reference counter between d
ifferent shared_ptr types
template<class _Ts> friend class shared_ptr;
template<class _Tw> friend class weak_ptr;
private:
T *px; //!< Native pointer
shared_ptr_count *pn; //!< Reference counter
// For use by weak_ptr
shared_ptr(T *p, shared_ptr_count *c)
{
pn = c;
px = p;
}
public: public:
/// The type of the managed object, aliased as member type /// The type of the managed object, aliased as member type
typedef T element_type; typedef T element_type;
/// @brief Default constructor /// @brief Default constructor
shared_ptr(void) : // never throws shared_ptr()
px(NULL), {
pn() px = NULL;
{ pn = NULL;
} }
/// @brief Constructor with the provided pointer to manage /// @brief Constructor with the provided pointer to manage
explicit shared_ptr(T* p) : // may throw std::bad_alloc explicit shared_ptr(T *p)
//px(p), would be unsafe as acquire() may throw, which would call release( {
) in destructor pn = new shared_ptr_count();
pn() acquire(p); // may throw std::bad_alloc
{ }
acquire(p); // may throw std::bad_alloc /// @brief Constructor to share ownership. Warning : to be used for pointer_c
} ast only ! (does not manage two separate <T> and <U> pointers)
/// @brief Constructor to share ownership. Warning : to be used for pointer_ template<class U> shared_ptr(const shared_ptr<U> &ptr, T *p)
cast only ! (does not manage two separate <T> and <U> pointers) {
template <class U> pn = ptr.pn;
shared_ptr(const shared_ptr<U>& ptr, T* p) : acquire(p); // may throw std::bad_alloc
//px(p), would be unsafe as acquire() may throw, which would call release() }
in destructor /// @brief Copy constructor to convert from another pointer type
pn(ptr.pn) template<class U> shared_ptr(const shared_ptr<U> &ptr)
{ {
acquire(p); // may throw std::bad_alloc pn = ptr.pn;
} acquire(static_cast<typename shared_ptr<T>::element_type*>(ptr.px)); //
/// @brief Copy constructor to convert from another pointer type will never throw std::bad_alloc
template <class U> }
shared_ptr(const shared_ptr<U>& ptr) : /// @brief Copy constructor (used by the copy-and-swap idiom)
//px(ptr.px), shared_ptr(const shared_ptr &ptr)
pn(ptr.pn) {
{ pn = ptr.pn;
acquire(static_cast<typename shared_ptr<T>::element_type*>(ptr.px)); / acquire(ptr.px); // will never throw std::bad_alloc
/ will never throw std::bad_alloc }
} /// @brief Assignment operator using the copy-and-swap idiom (copy constructo
/// @brief Copy constructor (used by the copy-and-swap idiom) r and swap method)
shared_ptr(const shared_ptr& ptr) : shared_ptr& operator=(shared_ptr ptr)
//px(ptr.px), {
pn(ptr.pn) swap(ptr);
{ return *this;
acquire(ptr.px); // will never throw std::bad_alloc }
} /// @brief the destructor releases its ownership
/// @brief Assignment operator using the copy-and-swap idiom (copy construct ~shared_ptr()
or and swap method) {
shared_ptr& operator=(shared_ptr ptr) release();
{ }
swap(ptr); /// @brief this reset releases its ownership
return *this; void reset()
} {
/// @brief the destructor releases its ownership release();
~shared_ptr(void) }
{ /// @brief this reset release its ownership and re-acquire another one
release(); void reset(T *p)
} {
/// @brief this reset releases its ownership release();
void reset(void) acquire(p);
{ }
release();
} /// @brief Swap method for the copy-and-swap idiom (copy constructor and swap
/// @brief this reset release its ownership and re-acquire another one method)
void reset(T* p) void swap(shared_ptr &lhs)
{ {
release(); std::swap(px, lhs.px);
acquire(p); std::swap(pn, lhs.pn);
} }
/// @brief Swap method for the copy-and-swap idiom (copy constructor and swa // reference counter operations :
p method) long use_count() const
void swap(shared_ptr& lhs) {
{ return (pn != NULL) ? pn->use_count() : 0;
std::swap(px, lhs.px); }
pn.swap(lhs.pn); operator bool() const
} {
return use_count() > 0;
// reference counter operations : }
operator bool() const bool unique() const
{ {
return (0 < pn.use_count()); return use_count() == 1;
} }
bool unique(void) const
{ // underlying pointer operations :
return (1 == pn.use_count()); T& operator*() const
} {
long use_count(void) const return *px;
{ }
return pn.use_count(); T* operator->() const
} {
return px;
// underlying pointer operations : }
T& operator*() const T* get() const
{ {
return *px; return px;
} }
T* operator->() const
{
return px;
}
T* get(void) const
{
return px;
}
private: private:
/// @brief acquire/share the ownership of the px pointer, initializing the r /// @brief acquire/share the ownership of the px pointer, initializing the re
eference counter ference counter
void acquire(T* p) void acquire(T *p)
{ {
pn.acquire(p); if (p != NULL)
px = p; // here it is safe to acquire the ownership of the provided raw {
pointer, where exception cannot be thrown any more if (pn == NULL)
} pn = new shared_ptr_count();
pn->acquire(p);
/// @brief release the ownership of the px pointer, destroying the object wh }
en appropriate px = p; // here it is safe to acquire the ownership of the provided raw po
void release(void) inter, where exception cannot be thrown any more
{ }
pn.release(px);
px = NULL; /// @brief release the ownership of the px pointer, destroying the object whe
} n appropriate
void release(void)
{
if (pn != NULL)
{
pn->release(px);
pn = NULL;
}
px = NULL;
}
};
template<class T> class weak_ptr
{
private: private:
// This allow pointer_cast functions to share the reference counter between T *px;
different shared_ptr types shared_ptr_count *pn;
template<class U>
friend class shared_ptr;
private: public:
T* px; //!< Native pointer weak_ptr()
shared_ptr_count pn; //!< Reference counter {
px = NULL;
pn = NULL;
}
weak_ptr(const shared_ptr<T> &sptr)
{
pn = sptr.pn;
px = sptr.px;
if (pn != NULL)
pn->weakAcquire();
}
~weak_ptr()
{
if (pn != NULL)
pn->weakRelease();
}
void
reset()
{
if (pn != NULL)
{
pn->weakRelease();
pn = NULL;
}
px = NULL;
}
shared_ptr<T>
lock() const
{
if ((pn != NULL) && pn->weakLock())
{
return shared_ptr<T>(px, pn);
}
return shared_ptr<T>();
}
}; };
// comparaison operators // comparaison operators
template<class T, class U> bool operator==(const shared_ptr<T>& l, const shared_ template<class T, class U> bool operator==(const shared_ptr<T> &l, const shared_
ptr<U>& r) ptr<U> &r)
{
return (l.get() == r.get());
}
template<class T> bool operator==(const shared_ptr<T> &l, nullptr_t r)
{
return l.get() == NULL;
}
template<class T, class U> bool operator!=(const shared_ptr<T> &l, const shared_
ptr<U> &r)
{ {
return (l.get() == r.get()); return (l.get() != r.get());
} }
template<class T, class U> bool operator!=(const shared_ptr<T>& l, const shared_
ptr<U>& r) template<class T> bool operator!=(const shared_ptr<T> &l, nullptr_t r)
{ {
return (l.get() != r.get()); return l.get() != NULL;
} }
template<class T, class U> bool operator<=(const shared_ptr<T>& l, const shared_
ptr<U>& r) template<class T, class U> bool operator<=(const shared_ptr<T> &l, const shared_
ptr<U> &r)
{ {
return (l.get() <= r.get()); return (l.get() <= r.get());
} }
template<class T, class U> bool operator<(const shared_ptr<T>& l, const shared_p
tr<U>& r) template<class T, class U> bool operator<(const shared_ptr<T> &l, const shared_p
tr<U> &r)
{ {
return (l.get() < r.get()); return (l.get() < r.get());
} }
template<class T, class U> bool operator>=(const shared_ptr<T>& l, const shared_
ptr<U>& r) template<class T, class U> bool operator>=(const shared_ptr<T> &l, const shared_
ptr<U> &r)
{ {
return (l.get() >= r.get()); return (l.get() >= r.get());
} }
template<class T, class U> bool operator>(const shared_ptr<T>& l, const shared_p
tr<U>& r) template<class T, class U> bool operator>(const shared_ptr<T> &l, const shared_p
tr<U> &r)
{ {
return (l.get() > r.get()); return (l.get() > r.get());
} }
// static cast of shared_ptr // static cast of shared_ptr
template<class T, class U> template<class T, class U> shared_ptr<T> static_pointer_cast(const shared_ptr<U>
shared_ptr<T> static_pointer_cast(const shared_ptr<U>& ptr) &ptr)
{ {
return shared_ptr<T>(ptr, static_cast<typename shared_ptr<T>::element_type*> (ptr.get())); return shared_ptr<T>(ptr, static_cast<typename shared_ptr<T>::element_type*>( ptr.get()));
} }
// dynamic cast of shared_ptr // dynamic cast of shared_ptr
template<class T, class U> template<class T, class U> shared_ptr<T> dynamic_pointer_cast(const shared_ptr<U
shared_ptr<T> dynamic_pointer_cast(const shared_ptr<U>& ptr) > &ptr)
{ {
T* p = dynamic_cast<typename shared_ptr<T>::element_type*>(ptr.get()); T *p = dynamic_cast<typename shared_ptr<T>::element_type*>(ptr.get());
if (NULL != p) if (NULL != p)
{ {
return shared_ptr<T>(ptr, p); return shared_ptr<T>(ptr, p);
} }
else else
{ {
return shared_ptr<T>(); return shared_ptr<T>();
} }
} }
// make shared object // make shared object
template<typename T, typename... Args> template<typename T, typename ... Args> inline shared_ptr<T> make_shared(Args &&
inline shared_ptr<T> make_shared(Args&&... args) ... args)
{ {
return shared_ptr<T>(new T(args...)); return shared_ptr<T>(new T(args...));
} }
#endif #endif
 End of changes. 28 change blocks. 
223 lines changed or deleted 313 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)