Skip to content

Commit

Permalink
Rework Some
Browse files Browse the repository at this point in the history
- Stop using std::shared_ptr at all
- Don't reference raw pointers - this leads to memory leaks
- Tabs to spaces
  • Loading branch information
lisitsyn committed Jun 7, 2016
1 parent ed0cc9e commit 2dbcaa6
Showing 1 changed file with 107 additions and 92 deletions.
199 changes: 107 additions & 92 deletions src/shogun/base/some.h
Expand Up @@ -11,101 +11,116 @@
namespace shogun
{

/** @class Shogun synonym for the std::shared_ptr. Employs
* exactly the same strategy for reference counting
* as std::shared_ptr: any operation involving copying increases
* the count and once deleted this wrapper decreases the counter.
*
* Note: Due to SG_REF/SG_UNREF used in Shogun now, it also imitates
* Shogun references so that shared_ptr counter should always
* be equal to the Shogun's object reference count. This will stay
* until SG_REF/SG_UNREF are gone.
*
*/
template <typename T>
class Some : protected std::shared_ptr<T>
{
public:
Some() = delete;
Some(const std::shared_ptr<T>& shared);
Some(const Some<T>& other);
Some(Some<T>&& other);
Some& operator=(const Some<T>& other);
Some& operator=(T* other);
~Some();
/** @class Shogun synonym for the std::shared_ptr. Employs
* exactly the same strategy for reference counting
* as std::shared_ptr: any operation involving copying increases
* the count and once deleted this wrapper decreases the counter.
*
*/
template <typename T>
class Some
{
public:
Some(const Some<T>& other);
explicit Some(T* other);
Some& operator=(T* other);
~Some();

/** Casts the underlying object back to raw pointer
*
* @return raw pointer (with SG_REF)
*/
operator T*();
/** Call member function or access member of T
*
* @return raw pointer (without SG_REF)
*/
T* operator->();
private:
using std::shared_ptr<T>::get;
using std::shared_ptr<T>::reset;
};
static Some<T> from_raw(T* raw);

template <typename T>
Some<T>::Some(const std::shared_ptr<T>& shared)
: std::shared_ptr<T>(shared)
{
}
template <typename T>
Some<T>::Some(const Some<T>& other)
: std::shared_ptr<T>(other)
{
}
template <typename T>
Some<T>::Some(Some<T>&& other)
: std::shared_ptr<T>(other)
{
}
template <typename T>
Some<T>::~Some()
{
}
template <typename T>
Some<T>& Some<T>::operator=(T* other)
{
this->reset(other);
SG_REF(this->get());
return *this;
}
template <typename T>
Some<T>::operator T*()
{
T* ptr = this->get();
SG_REF(ptr);
return ptr;
}
template <typename T>
T* Some<T>::operator->()
{
T* ptr = this->get();
return ptr;
}
/** Casts the underlying object back to raw pointer
*
* Be careful to SG_REF obtained pointer if you start to own it.
*
* @return raw pointer (without SG_REF)
*/
operator T*();
/** Call member function or access member of T
*
* @return raw pointer (without SG_REF)
*/
T* operator->();
private:
Some();
void unref();
void ref();
private:
T* raw;
};

/** Creates an instance of any class
* that is wrapped with a shared pointer like
* structure @ref Some
*
* @param args arguments to construct instance of T with (T should
* have compatible constructor)
*
* @return a shared pointer that holds created instance of @ref T
*
*/
template <typename T, class... Args>
Some<T> some(Args&&... args)
{
T* ptr = new T(args...);
SG_REF(ptr);
return std::shared_ptr<T>(ptr, [](T* p) { SG_UNREF(p); });
}
template <typename T>
Some<T>::Some()
: raw(nullptr)
{
}
template <typename T>
Some<T>::Some(const Some<T>& other)
: raw(other.raw)
{
ref();
}
template <typename T>
Some<T>::Some(T* other)
: raw(other)
{
ref();
}
template <typename T>
Some<T>& Some<T>::operator=(T* other)
{
unref();
raw = other;
ref();
return *this;
}
template <typename T>
Some<T>::~Some()
{
unref();
}
template <typename T>
Some<T>::operator T*()
{
return raw;
}
template <typename T>
T* Some<T>::operator->()
{
return raw;
}
template <typename T>
void Some<T>::ref()
{
SG_REF(raw);
}
template <typename T>
void Some<T>::unref()
{
SG_UNREF(raw);
}
template <typename T>
Some<T> Some<T>::from_raw(T* raw)
{
Some<T> result(raw);
return result;
}

/** Creates an instance of any class
* that is wrapped with a shared pointer like
* structure @ref Some
*
* @param args arguments to construct instance of T with (T should
* have compatible constructor)
*
* @return a shared pointer that holds created instance of @ref T
*
*/
template <typename T, class... Args>
Some<T> some(Args&&... args)
{
T* ptr = new T(args...);
return Some<T>::from_raw(ptr);
}

};

Expand Down

0 comments on commit 2dbcaa6

Please sign in to comment.