Click here to Skip to main content
15,885,546 members
Articles / Programming Languages / C++

Implementing a std::map Replacement that Never Runs Out of Memory and Instructions on Producing an ARPA Compliant Language Model to Test the Implementation

Rate me:
Please Sign up or sign in to vote.
5.00/5 (10 votes)
14 Dec 2008CPOL9 min read 53.5K   276   36  
An article on improving STL containers to cache to disk in order to lift memory limitation issues.
#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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Canada Canada
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.

Comments and Discussions