You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
252 lines
8.0 KiB
252 lines
8.0 KiB
#ifndef _DEUNIQUEPTR_HPP
|
|
#define _DEUNIQUEPTR_HPP
|
|
/*-------------------------------------------------------------------------
|
|
* drawElements C++ Base Library
|
|
* -----------------------------
|
|
*
|
|
* Copyright 2014 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
*//*!
|
|
* \file
|
|
* \brief Unique pointer.
|
|
*//*--------------------------------------------------------------------*/
|
|
|
|
#include "deDefs.hpp"
|
|
|
|
namespace de
|
|
{
|
|
|
|
//! Unique pointer self-test.
|
|
void UniquePtr_selfTest (void);
|
|
|
|
// Hide implementation-private types in a details namespace.
|
|
namespace details
|
|
{
|
|
|
|
//! Auxiliary struct used to pass references between unique pointers. To
|
|
//! ensure that managed pointers are deleted exactly once, this type should
|
|
//! not appear in user code.
|
|
template<typename T, class D>
|
|
struct PtrData
|
|
{
|
|
PtrData (T* p, D d) : ptr(p), deleter(d) {}
|
|
|
|
template <typename T2, class D2>
|
|
PtrData (const PtrData<T2, D2>& d) : ptr(d.ptr), deleter(d.deleter) {}
|
|
|
|
T* ptr;
|
|
D deleter;
|
|
};
|
|
|
|
template<typename T, class D>
|
|
class UniqueBase
|
|
{
|
|
public:
|
|
typedef T element_type;
|
|
typedef D deleter_type;
|
|
|
|
T* get (void) const throw() { return m_data.ptr; } //!< Get stored pointer.
|
|
D getDeleter (void) const throw() { return m_data.deleter; }
|
|
T* operator-> (void) const throw() { return get(); } //!< Get stored pointer.
|
|
T& operator* (void) const throw() { return *get(); } //!< De-reference stored pointer.
|
|
operator bool (void) const throw() { return !!get(); }
|
|
|
|
protected:
|
|
UniqueBase (T* ptr, D deleter) : m_data(ptr, deleter) {}
|
|
UniqueBase (PtrData<T, D> data) : m_data(data) {}
|
|
~UniqueBase (void);
|
|
|
|
void reset (void); //!< Delete previous pointer, set to null.
|
|
PtrData<T, D> releaseData (void) throw(); //!< Relinquish ownership, return pointer data.
|
|
void assignData (PtrData<T, D> data); //!< Set new pointer, delete previous pointer.
|
|
|
|
private:
|
|
PtrData<T, D> m_data;
|
|
};
|
|
|
|
template <typename T, class D>
|
|
UniqueBase<T, D>::~UniqueBase (void)
|
|
{
|
|
reset();
|
|
}
|
|
|
|
template <typename T, class D>
|
|
void UniqueBase<T, D>::reset (void)
|
|
{
|
|
if (m_data.ptr != DE_NULL)
|
|
{
|
|
m_data.deleter(m_data.ptr);
|
|
m_data.ptr = DE_NULL;
|
|
}
|
|
}
|
|
|
|
template <typename T, class D>
|
|
PtrData<T, D> UniqueBase<T, D>::releaseData (void) throw()
|
|
{
|
|
PtrData<T, D> data = m_data;
|
|
m_data.ptr = DE_NULL;
|
|
return data;
|
|
}
|
|
|
|
template <typename T, class D>
|
|
void UniqueBase<T, D>::assignData (PtrData<T, D> data)
|
|
{
|
|
if (data.ptr != m_data.ptr)
|
|
{
|
|
reset();
|
|
m_data = data;
|
|
}
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*//*!
|
|
* \brief Movable unique pointer
|
|
*
|
|
* A MovePtr is smart pointer that retains sole ownership of a pointer and
|
|
* destroys it when it is destroyed (for example when it goes out of scope).
|
|
*
|
|
* A MovePtr can be copied and assigned to. The pointer ownership is moved to
|
|
* the newly constructer or assigned-to MovePtr. Upon assignment to a
|
|
* MovePtr, the previously managed pointer is deleted.
|
|
*
|
|
*//*--------------------------------------------------------------------*/
|
|
template<typename T, class Deleter = DefaultDeleter<T> >
|
|
class MovePtr : public UniqueBase<T, Deleter>
|
|
{
|
|
public:
|
|
MovePtr (void) : UniqueBase<T, Deleter> (DE_NULL, Deleter()) {}
|
|
explicit MovePtr (T* ptr, Deleter deleter = Deleter()) : UniqueBase<T, Deleter> (ptr, deleter) {}
|
|
MovePtr (MovePtr<T, Deleter>& other) : UniqueBase<T, Deleter> (other.releaseData()) {}
|
|
|
|
MovePtr& operator= (MovePtr<T, Deleter>& other);
|
|
T* release (void) throw();
|
|
void clear (void) { this->reset(); }
|
|
|
|
// These implicit by-value conversions to and from a PtrData are used to
|
|
// allow copying a MovePtr by value when returning from a function. To
|
|
// ensure that the managed pointer gets deleted exactly once, the PtrData
|
|
// should only exist as a temporary conversion step between two MovePtrs.
|
|
MovePtr (PtrData<T, Deleter> data) : UniqueBase<T, Deleter> (data) {}
|
|
MovePtr& operator= (PtrData<T, Deleter> data);
|
|
|
|
template<typename U, class Del2>
|
|
operator PtrData<U, Del2> (void) { return this->releaseData(); }
|
|
};
|
|
|
|
template<typename T, class D>
|
|
MovePtr<T, D>& MovePtr<T,D>::operator= (PtrData<T, D> data)
|
|
{
|
|
this->assignData(data);
|
|
return *this;
|
|
}
|
|
|
|
template<typename T, class D>
|
|
MovePtr<T, D>& MovePtr<T,D>::operator= (MovePtr<T, D>& other)
|
|
{
|
|
return (*this = other.releaseData());
|
|
}
|
|
|
|
//! Steal the managed pointer. The caller is responsible for explicitly
|
|
//! deleting the returned pointer.
|
|
template<typename T, class D>
|
|
inline T* MovePtr<T,D>::release (void) throw()
|
|
{
|
|
return this->releaseData().ptr;
|
|
}
|
|
|
|
//! Construct a MovePtr from a pointer.
|
|
template<typename T>
|
|
inline MovePtr<T> movePtr (T* ptr) { return MovePtr<T>(ptr); }
|
|
|
|
//! Allocate and construct an object and return its address as a MovePtr.
|
|
template<typename T>
|
|
inline MovePtr<T> newMovePtr (void) { return MovePtr<T>(new T()); }
|
|
template<typename T, typename P0>
|
|
inline MovePtr<T> newMovePtr (P0 p0) { return MovePtr<T>(new T(p0)); }
|
|
template<typename T, typename P0, typename P1>
|
|
inline MovePtr<T> newMovePtr (P0 p0, P1 p1) { return MovePtr<T>(new T(p0, p1)); }
|
|
template<typename T, typename P0, typename P1, typename P2>
|
|
inline MovePtr<T> newMovePtr (P0 p0, P1 p1, P2 p2) { return MovePtr<T>(new T(p0, p1, p2)); }
|
|
|
|
/*--------------------------------------------------------------------*//*!
|
|
* \brief Unique pointer
|
|
*
|
|
* UniquePtr is smart pointer that retains sole ownership of a pointer
|
|
* and destroys it when UniquePtr is destroyed (for example when UniquePtr
|
|
* goes out of scope).
|
|
*
|
|
* UniquePtr is not copyable or assignable. Pointer ownership can be transferred
|
|
* from a UniquePtr only explicitly with the move() member function.
|
|
*
|
|
* A UniquePtr can be constructed from a MovePtr. In this case it assumes
|
|
* ownership of the pointer from the MovePtr. Because a UniquePtr cannot be
|
|
* copied, direct initialization syntax must be used, i.e.:
|
|
*
|
|
* MovePtr<Foo> createFoo (void);
|
|
* UniquePtr<Foo> fooPtr(createFoo()); // NOT fooPtr = createFoo();
|
|
*
|
|
*//*--------------------------------------------------------------------*/
|
|
template<typename T, class Deleter = DefaultDeleter<T> >
|
|
class UniquePtr : public UniqueBase<T, Deleter>
|
|
{
|
|
public:
|
|
explicit UniquePtr (T* ptr, Deleter deleter = Deleter());
|
|
UniquePtr (PtrData<T, Deleter> data);
|
|
MovePtr<T, Deleter> move (void);
|
|
|
|
private:
|
|
UniquePtr (const UniquePtr<T>& other); // Not allowed!
|
|
UniquePtr operator= (const UniquePtr<T>& other); // Not allowed!
|
|
};
|
|
|
|
/*--------------------------------------------------------------------*//*!
|
|
* \brief Construct unique pointer.
|
|
* \param ptr Pointer to be managed.
|
|
*
|
|
* Pointer ownership is transferred to the UniquePtr.
|
|
*//*--------------------------------------------------------------------*/
|
|
template<typename T, class Deleter>
|
|
inline UniquePtr<T, Deleter>::UniquePtr (T* ptr, Deleter deleter)
|
|
: UniqueBase<T, Deleter> (ptr, deleter)
|
|
{
|
|
}
|
|
|
|
template<typename T, class Deleter>
|
|
inline UniquePtr<T, Deleter>::UniquePtr (PtrData<T, Deleter> data)
|
|
: UniqueBase<T, Deleter> (data)
|
|
{
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*//*!
|
|
* \brief Relinquish ownership of pointer.
|
|
*
|
|
* This method returns a MovePtr that now owns the pointer. The pointer in
|
|
* the UniquePtr is set to null.
|
|
*//*--------------------------------------------------------------------*/
|
|
template<typename T, class Deleter>
|
|
inline MovePtr<T, Deleter> UniquePtr<T, Deleter>::move (void)
|
|
{
|
|
return MovePtr<T, Deleter>(this->releaseData());
|
|
}
|
|
|
|
} // details
|
|
|
|
using details::UniquePtr;
|
|
using details::MovePtr;
|
|
using details::newMovePtr;
|
|
|
|
} // de
|
|
|
|
#endif // _DEUNIQUEPTR_HPP
|