auto_ptr for Irrlicht

A forum to store posts deemed exceptionally wise and useful
Post Reply
schick
Posts: 230
Joined: Tue Oct 07, 2003 3:55 pm
Location: Germany
Contact:

auto_ptr for Irrlicht

Post by schick »

Hey guys,

long time ago since my last post. I did some traveling through North America (living in germany by the way). I am just at a friends house and had a look how Irrlicht was growing... nothing to say but amazing.

I will have a look at all the nice features Irrlicht now provides. Thanks everyone for contributing.

But in fact there is a, well, basic thing missing a auto_ptr for IUnknown. So you dont have to care about grabbing and dropping the IUnknown objects anymore. It will be done for you automatically. It can be used nearly the same way as std::auto_ptr.

Here is the code, happy using. If there are some errors please report.

Code: Select all

#ifndef IRR_AUTO_PTR
#define IRR_AUTO_PTR

#include <iosfwd> // std::basic_ostream
#include <cassert> // assert 

namespace irr
{

template <class T> class auto_ptr
{
  private:
    T*  ptr;  
  
  public:
    auto_ptr()
      : ptr(NULL)
    {
    }
    
    ~auto_ptr()
    {
      if(ptr)
        ptr->::irr::IUnknown::drop();
    }
    
    auto_ptr(T* p)
      : ptr(NULL)
    {
      if(p && !ptr)
      {
        p->::irr::IUnknown::grab();
        ptr = p;
      }
    }
    
    auto_ptr(const auto_ptr<T>& p)
    {
      if(ptr || !p)
        return;
      
      p.ptr->::irr::IUnknown::grab();
      ptr = p.ptr;
    }
    
    auto_ptr<T>& operator=(const auto_ptr<T>& p)
    {
      if(ptr || !p)
        return;
      
      p.ptr->::irr::IUnknown::grab();
      ptr = p.ptr;
      
      return *this;
    }  

    T* get() const
    { 
      return ptr; 
    }
    
    T& operator*() const
    {
      assert(ptr);
      return *ptr;
    }
    
    void reset()
    {
      if(ptr)
      {
        ptr->::irr::IUnknown::drop();
        ptr = NULL;
      }
    }
    
    T* operator->() const
    { 
      assert(ptr);  
      return ptr; 
    }
    
    operator bool() const
    {
      return ptr;
    }
    
    bool operator!() const
    {
      return ptr;
    }                      
};

template<class T, class U> inline bool operator==(auto_ptr<T> const & a, auto_ptr<U> const & b)
{
  return a.get() == b.get();
}

template<class T, class U> inline bool operator!=(auto_ptr<T> const & a, auto_ptr<U> const & b)
{
  return a.get() != b.get();
}

template<class T, class U> inline bool operator<(auto_ptr<T> const & a, auto_ptr<U> const & b)
{
  return a.get() < b.get();
}

template<class T> std::ostream & operator<< (std::ostream & os, auto_ptr<T> const & p)
{
  os << p.get();
  return os;
}

} // end namespace irr

#endif // endif IRR_AUTO_PTR

Last edited by schick on Thu Sep 01, 2005 11:23 pm, edited 2 times in total.
Please send me an e-mail instead of a private message.
Midnight
Posts: 1772
Joined: Fri Jul 02, 2004 2:37 pm
Location: Wonderland

Post by Midnight »

Oh no the germans are comming! lol

where in north america did you visit?

Nice to see you again welcome back yes the newest version of Irrlicht was my favorite of all time the Guice project has been taken to new heights because of some of the features.

I'm not to sure what your class does exactly would you care to explain a bit about it for me and the rest of the noobs?
Midnight
Posts: 1772
Joined: Fri Jul 02, 2004 2:37 pm
Location: Wonderland

Post by Midnight »

After reading a short article about this function I think I understand its uses.

but I don't understand why you would want this...

Is it just to insure against coding mistakes? where a pointer might not be deleted because it first returned some other value before reaching the end of the scope? or rather before it gets to the destructor of a pointer??

just what is the purpose of this? and furthermore what happens if you do have a memory leak? does it ruin your ram?

Thanks for this btw not sure if I'll use it but it's always nice to have things before you even know you need them.
Masdus
Posts: 186
Joined: Tue Aug 26, 2003 1:13 pm
Location: Australia

Post by Masdus »

main purpose of auto pointers are to avoid memory leaks from not remembering to drop a resource. Basically if the app ends and the resource has not been dropped, the memory it was allocated is not freeed. So if you were to run a simple app that did not drop a resource over and over again you should see your free memory drop each time.
I think they can also help with memory leaks caused by things like apps crashing, but that might be one of the more complicated smart pointer types.
Memory leaks do nothing permanent to your ram, plus turning off your machine will free up the lost space.
Midnight
Posts: 1772
Joined: Fri Jul 02, 2004 2:37 pm
Location: Wonderland

Post by Midnight »

Shouldn't this be something in the engine then that can be used like anything else?

Thanks for the info I always worried about damaging my system with pointers the way memory leaks are talked about I thought it was permanent.

Is there any dangers I should be aware of when coding?
If so what are they?
Anyone know where I can read about this in detail possibly?
schick
Posts: 230
Joined: Tue Oct 07, 2003 3:55 pm
Location: Germany
Contact:

Post by schick »

The Irrlicht auto_ptr will do call IUnknown::grab() and IUnknown::drop() for you, thats it. So you dont need to care about the pointer itself anymore.

For example:

You want to use the IFileSystem. The regular way:

Code: Select all

// pseudo code
IFileSystem* fs = IrrlichtDevice->getFileSystem();
if(fs)
  fs->grab();

// do something

if(fs)
  fs->drop();
With irr::auto_ptr it looks like:

Code: Select all

// pseudo code
auto_ptr< IFileSystem > fs(IrrlichtDevice->getFileSystem());
The auto_ptr will call grab and drop for you.

// the grabbing and dropping of IUnknown ensures that the pointer will always be valid. Otherwise something could delete the object behind your pointer and you have a dead pointer pointing to nowhere.

I arrived in NewYork, went up to NiagraFalls, Toronto, Winnipeg, Edomton, Vancouver (BC), Portland, SanFrancisco, L.A., LasVegas, GrandCanyon, Houston. I am in Houston but will go further probably to Miami.
Please send me an e-mail instead of a private message.
Midnight
Posts: 1772
Joined: Fri Jul 02, 2004 2:37 pm
Location: Wonderland

Post by Midnight »

oh nice I finally understand what this is for and that would really help optimize the code would it not?

decrease typing time shortly and typing mistakes possible revision time... good stuff.
pfo
Posts: 370
Joined: Mon Aug 29, 2005 10:54 pm
Location: http://web.utk.edu/~pfox1

Post by pfo »

Midnight: I'm pretty sure on windows xp / 2000, for each application there is a limited ammount of memory that that app can access. Any attempts to access outside of that area will cause an access violation (obviously). So it should be impossible to mess with memory outside your application's boundary (unless you're some eLiTe HaX0r that writes a buffer overflow). And when an app is de-allocated, it simply takes that entire chunk of memory and returns it to the OS, so if you have memory leaks they should only affect the app while it's running. Closing the program should free all of them. The problem with memory leaks is that, for instance, you dynamically allocate objects and don't release them when you should, the memory size will keep growing. Evenutally, it will get big enough that it has to start paging to virtual memory, and when it starts doing this a lot, the app's performance will slow.
Guest

Post by Guest »

Why have I been getting away without needing to use ->grab() on as in your example the filesystem, or anything "get".?

I thought only objects created with a call that started with "create" had to be manually dropped?

Is grab implicitly called for other calls?

If I don't use grab does this mean my reference counting is wrong and IRRLICHT will not release things automatically as I thought it was doing?

thanks
Guest

Post by Guest »

These functions are great. Does anyone have a function to turn towards a vector by a certain number of units? This is so i can get a ship to slowly face a new course.
zenaku
Posts: 212
Joined: Tue Jun 07, 2005 11:23 pm

Post by zenaku »

What do you do for some pointers that need to be dropped but not grabbed?

From Example 03 -

Code: Select all

	/*
	To animate something in this boring scene consisting only of one tetraeder,
	and to show, that you now can use your scene node like any other scene
	node in the engine, we add an animator to the scene node, which rotates
	the node a little bit.
	*/

	scene::ISceneNodeAnimator* anim = 
		smgr->createRotationAnimator(core::vector3df(0.8f, 0, 0.8f));

	myNode->addAnimator(anim);
	anim->drop();

Functions that start with 'create', eg. createRotationAnimator() need to be dropped but not grabbed. Functions that start with 'get' like 'getFileSystem()' DO need to be grabbed before being dropped.

The auto_ptr is a good idea, but some of the irrlicht conventions will make it confusing to use correctly. You still have to know when to grab and drop things. There's no way it can be automatic. People will start using auto_ptrs for 'create' functions and end up with memory leaks.

Code: Select all

// bad psuedo code
auto_ptr< ISceneNodeAnimator> anim(smgr->createRotationAnimator()); 

// The extra grab caused by auto_ptr will leak memory when anim goes out of scope
Post Reply