|
#ifndef __shared_auto_ptr_H__
#define __shared_auto_ptr_H__
/* This file exposes 1 public usable template class:
- shared_auto_ptr:
Use a shared_auto_ptr in order to keep track of a resource and automatically invoke a delete on the
destruction of the last referant.
To call it, use the following syntax:
shared_auto_ptr<T> var(T* ptr);
or:
shared_auto_ptr<T> var
The template has destructor, copy constructor and assignment logic to keep track of the referants.
In order to later extract the kept resource, use the following call:
T* var.get()
or simply use the deferencing operator (overloaded to return T*):
T * var->
For individual method documentation, refer to the template definition lower.
*/
#pragma warning( disable : 4290 )
template <class T> class shared_auto_ptr;
using namespace std;
/* *************************** interfaces ************************** */
// - contained_auto_ptr:
// The contained_auto_ptr is the container of a unique ptr that holds a count
// of the referants.
// It hides the copy constructor and assignment operator in its private section
// in order to ensure that it is never constructed or assigned to another object
// without going through the shared_auto_ptr.
// There are no public method in this class since it is expected to exclusively be
// called by its friend class shared_auto_ptr<T>.
template <class T> class contained_auto_ptr
{
public:
friend class shared_auto_ptr<T>;
protected:
// The GetContainer acts as a static constructor, but constructs only if no
// other contained_auto_ptr<T> points to the same pointer p.
static contained_auto_ptr<T> *GetContainer(T* p = NULL) throw();
// In order to extract the value pointed by the object, use the get() method.
T *get() const throw();
// Destructor...
~contained_auto_ptr() throw();
private:
// Constructor: never call directly. Use GetContainer instead...
contained_auto_ptr(T* p = NULL) throw();
// This static map holds the equivalence between pointers and contained_auto_ptr objects
// already created.
static map<uintptr_t, contained_auto_ptr<T>*> m_equivalenceMap;
// We hide the copy constructor and the assignment operators to ensure they
// are never used.
contained_auto_ptr(const contained_auto_ptr&) throw();
void operator=(const contained_auto_ptr&) throw();
int m_count; // holds the count of the referants.
T *_ptr; // T* being held by the object.
};
// - shared_auto_ptr (*** PUBLIC INTERFACE ***):
// The shared_auto_ptr allows for the creation of a referant to a location in memory. It may create a
// contained_auto_ptr object in the event that it is the first referant of the memory location. Upon the
// destruction of the last referant, the memory allocated will be deleted.
template <class T> class shared_auto_ptr
{
public:
// Constructor:
// REQUIREMENTS:
// - p must point to the memory location to track.
// PROMISES:
// - upon destruction of the shared_auto_ptr object, p will be deleted only
// when the last referant will have been deleted.
shared_auto_ptr(T* p = NULL) throw();
// Destructor:
// REQUIREMENTS:
// - none.
// PROMISES:
// - upon destruction of the shared_auto_ptr object, the pointer provided upon construction
// or obtained through the assignment operator will be deleted only
// when the last referant will have been deleted.
~shared_auto_ptr() throw();
// Copy constructor:
// REQUIREMENTS:
// - none.
// PROMISES:
// - upon destruction of the shared_auto_ptr object, the pointer provided upon construction
// or obtained through the assignment operator will be deleted only
// when the last referant will have been deleted.
shared_auto_ptr(const shared_auto_ptr&) throw();
// assignment operator:
// REQUIREMENTS:
// - none.
// PROMISES:
// - upon destruction of the shared_auto_ptr object, the pointer provided upon construction
// or obtained through the assignment operator will be deleted only
// when the last referant will have been deleted.
void operator=(const shared_auto_ptr&) throw();
// get():
// REQUIREMENTS:
// - Do not use the returned pointer outside the scope where it was obtained (as when that
// scope is left, the shared_auto_ptr object may be deleted, and the memory associated with
// it also consequently).
// PROMISES:
// - Within the same scope, the returned pointer will be good.
T *get() const throw();
// -> operator:
// REQUIREMENTS:
// - Do not use the returned pointer outside the scope where it was obtained (as when that
// scope is left, the shared_auto_ptr object may be deleted, and the memory associated with
// it also consequently).
// PROMISES:
// - Within the same scope, the returned pointer will be good.
T *operator->() const throw() { return get(); }
private:
contained_auto_ptr<T> *m_contained_auto_ptr;
};
/* ******************** shared_auto_ptr support ******************** */
template <class T> map<uintptr_t, contained_auto_ptr<T>*> contained_auto_ptr<T>::m_equivalenceMap;
template <class T> contained_auto_ptr<T> *contained_auto_ptr<T>::GetContainer(T* p) throw()
{
if ((p != NULL) && (contained_auto_ptr<T>::m_equivalenceMap.find((uintptr_t)p) != contained_auto_ptr<T>::m_equivalenceMap.end()))
{
return contained_auto_ptr<T>::m_equivalenceMap[(uintptr_t)p];
}
else
{
return new contained_auto_ptr<T>(p);
}
}
template <class T> contained_auto_ptr<T>::contained_auto_ptr(T* p) throw(): _ptr(p), m_count(0)
{
if (p)
{
contained_auto_ptr<T>::m_equivalenceMap[(uintptr_t)p] = this;
}
}
template <class T> contained_auto_ptr<T>::~contained_auto_ptr() throw()
{
contained_auto_ptr<T>::m_equivalenceMap.erase((uintptr_t)_ptr);
delete _ptr;
}
template <class T> T *contained_auto_ptr<T>::get() const throw()
{
return _ptr;
}
template <class T> shared_auto_ptr<T>::shared_auto_ptr(T* p) throw(): m_contained_auto_ptr(NULL)
{
m_contained_auto_ptr = contained_auto_ptr<T>::GetContainer(p);
m_contained_auto_ptr->m_count++;
}
template <class T> shared_auto_ptr<T>::~shared_auto_ptr() throw()
{
m_contained_auto_ptr->m_count--;
if (!m_contained_auto_ptr->m_count)
{
delete m_contained_auto_ptr;
}
}
template <class T> shared_auto_ptr<T>::shared_auto_ptr(const shared_auto_ptr& copy) throw()
{
copy.m_contained_auto_ptr->m_count++;
m_contained_auto_ptr = copy.m_contained_auto_ptr;
}
template <class T> void shared_auto_ptr<T>::operator=(const shared_auto_ptr& copy) throw()
{
if (copy.m_contained_auto_ptr != m_contained_auto_ptr)
{
contained_auto_ptr<T> *orig = m_contained_auto_ptr;
m_contained_auto_ptr = copy.m_contained_auto_ptr;
m_contained_auto_ptr->m_count++;
orig->m_count--;
if (!orig->m_count)
{
delete orig;
}
}
else
{
m_contained_auto_ptr->m_count++;
}
}
template <class T> T *shared_auto_ptr<T>::get() const throw()
{
if (m_contained_auto_ptr != NULL)
{
return m_contained_auto_ptr->get();
}
else
{
return NULL;
}
}
#pragma warning( default : 4290 )
#endif
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
Philippe Roy was a key contributor throughout his 20+ years career with many high-profile companies such as Nuance Communications, IBM (ViaVoice and ProductManager), VoiceBox Technologies, just to name a few. He is creative and proficient in OO coding and design, knowledgeable about the intellectual-property world (he owns many patents), tri-lingual, and passionate about being part of a team that creates great solutions.
Oh yes, I almost forgot to mention, he has a special thing for speech recognition and natural language processing... The magic of first seeing a computer transform something as chaotic as sound and natural language into intelligible and useful output has never left him.