Sign in to follow this  
yaustar

Memory Manager from Enginuity PtII

Recommended Posts

Given the source below would I be right in saying that creating an instance of any class that inherits from MMObject on the stack would be very dangerous? How would I go about creating a temporay variable in a function besides new-ing an object and ptr-Release() at the end? Thanks Source code from the article:
//! A base abstract class to manage heap memory use.
/*!
 Part of the memory management module. Holds a list of all newly created objects and also handles
 Garbarge Collection. Concept taken from
 <A HREF="http://www.gamedev.net/reference/articles/article1954.asp">Enginuity, Part II</A>.
 \sa MMPointer, MMDynamicBlob and MMBlob.
*/
#ifndef MMOBJECT_H
#define MMOBJECT_H

#include <list>

namespace yaustar
{
	class MMObject
	{
		private:
		//! A list of pointers to hold all the 'Live' objects.
		/*!
		 This list holds a pointer to all newly created objects that derieve from MMObject.
		*/
		static std::list<MMObject *> LiveObjects;

		//! A list of pointers to hold all the 'Dead' objects.
		/*!
		 This list holds a pointer to all objects that derieve from MMObject which are no longer
		 needed by any part of the program.
		*/
		static std::list<MMObject *> DeadObjects;

		//! Reference Counter.
		/*!
		 Keeps count of how many pointers are asscoiated with this object. When it is 0, it is moved
		 to the DeadObjects list.
		*/
		unsigned long RefCount;

		public:
		//! Constructor.
		/*!
		 Defaults the RefCount to 0 and adds itself to the LiveObjects list.
		*/
		MMObject(void);

		//! Destructor.
		/*!
		 Does nothing. Zip, nada, sweet FA.
		*/
		virtual ~MMObject(void)
		{
			// Do nothing
		}

		//! Increments RefCount by 1.
		void AddRef(void)
		{
			++RefCount;
		}

		//! Decreases RefCount by 1.
		void Release(void)
		{
			--RefCount;
			// Check if the RefCount is 0, if it is then move to the DeadObjects list
			if(RefCount <= 0)
			{
				LiveObjects.remove(this);
				DeadObjects.push_back(this);
			}
		}

		//! Frees up memory used by Dead Objects.
		/*!
		 Tranverses through the list of DeadObjects and destroys each object.
		*/
		static void CollectGarbarge(void);

		//! Frees up all objects dereived from this class.
		/*!
		 Tranverses through the list of LiveObjects and destroys each object. Not sure why it would
		 by used expect for the VERY end of the program in case the smart pointers don't do their
		 job.
		*/
		static void CollectAllObjects(void);

		//! Pure virtual function to get the size of the object.
		virtual unsigned long Size(void) = 0;
	};

	// Small #define to make it easier for derieved classes to implement MMObject::Size(void).
	#define AUTO_SIZE unsigned long size(void) { return sizeof(*this); }
}

#endif

//======================

#include "./MMObject.h"

using yaustar::MMObject;

// Declare the static variables
std::list <MMObject *> MMObject::LiveObjects;
std::list <MMObject *> MMObject::DeadObjects;

MMObject::MMObject(void)
{
	// Add itself to the list
	LiveObjects.push_back(this);
	// Reset the RefCount
	RefCount = 0;
}

void MMObject::CollectGarbarge(void)
{
	// For all the objects in the DeadObject list, destroy
	for(std::list <MMObject *>::iterator itr = DeadObjects.begin();
		itr != DeadObjects.end();
		++itr )
	{
		delete (*itr);
	}

	// Clear the list of pointers
	DeadObjects.clear();
}

void MMObject::CollectAllObjects(void)
{
	// Collect Garbarge
	MMObject::CollectGarbarge();

	// For all the objects in the LiveObject list, destroy
	for(std::list <MMObject *>::iterator itr = LiveObjects.begin();
		itr != LiveObjects.end();
		++itr)
	{
		delete (*itr);
	}

	// Clear the list of pointers
	LiveObjects.clear();
}

Share this post


Link to post
Share on other sites
Yes, doing it on the stack will break it. Read the discussion thread attached to the article; most of the issues and potential solutions are explored, but the ultimate conclusion is that this kind of object tracking is intrusive and unreliable. Grab a memory manager that just tracks new and delete - like, for example, Paul Nettle's MMGR) and chuck out the Enginuity one.

Share this post


Link to post
Share on other sites
Quote:
Original post by yaustar
Hmm... I would love to use boost but unfortunately it has yet been ported to the target platform (although it could be done). Would the STL shared pointer be a lot better?


STL doesn't have a shared pointer, I believe it was introduced in TR1 (Technical report 1) tough, but it isn't a part of the standard yet. If your STL implementation supports TR1 then you should use shared_ptr from that, I believe there are some minor differences between the TR1's shared_ptr and Boost's shared_ptr, but they are almost the same.

Share this post


Link to post
Share on other sites
Out of curiosity, what is your target platform? Boost is open source, doesn't require platform-specific code in the vast majority of its libraries, and it has a lot of workarounds for broken compilers. As long as your compiler isn't terribly noncompliant, you should be able to use most of Boost without problems. As an example, the smart pointers should work fine on just about any platform with a C++ compiler. Just download boost and include the headers you need. Most of boost doesn't even require a separate build.

Share this post


Link to post
Share on other sites
GCC 3.4.2 on the PC and GCC 4.0.2 (?) for the GP2X.

Compiling libraries is something relatively new to me especially if it is not my own code so without sounding too much like an idiot, how hard would it be under a Windows platform?

Share this post


Link to post
Share on other sites
I can tell you this in no uncertain terms; boost can be built on the GP2x, I know this for I have done it [grin]

(this assumes you have downloaded/extracted boost and obtained a copy of bjam and have it in your 'path')
download this and extract it
Then, copy the .jam file to
\tools\build\v1
which should be inside your boost dir
move the bat files so they are in the boost directory.

At this point you'll want to edit the 'armbuild.bat' file and change the paths so they match your system. By default boost builds and installs its self to c:\boost, which is how I've left it.

Once your paths are all set open a command window and cd to the boost directory
then issue the command 'armbuild'
and watch it work its magic [grin]

Once complete you have a shiney new set of .so and .a files to play with, move the .a files into the lib directory of your gcc install and put the include files in your gcc's 'Include' directory.

You should be all set at this point [smile]

Share this post


Link to post
Share on other sites
Building boost just for shared_ptr is rather dumb, considering that's entirely a header library. You could have just copied some headers over, and stripped the 'configuration bloat' from them.

By time you finish with this... you could have just written your own too. :(

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this