/**
 * @file
 * $Id$
 * $Revision$
 * $Author$
 * $Date$
 *
 * This file is part of The iWear Framework.
 *
 * The iWear Framework is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by the
 * Free Software Foundation as in version 2 of the License.

 * 
 * The iWear Framework is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * The iWear Framework; if not, write to the Free Software Foundation, Inc., 59
 * Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef __IWEAR_MEMORY_H
#define __IWEAR_MEMORY_H

namespace iwear
{

template<class T>
class SimpleDelete
{
public:
    SimpleDelete( ) { }
    void operator()( T*t ) { delete t; }
};
/**
 * This is a shared ptr similar to the boost one, but we allow a release and do
 * it a bit simpler.
 */
template<class T, class D > 
class shared_ptr
{
protected:

    D del;
    T * ptr;
    uint32_t* counter;

public:

    shared_ptr()
	: ptr(0), counter(new uint32_t())
    {
    }

    shared_ptr( T* p )
	: ptr( p ), counter(new uint32_t())
    {
    }

    shared_ptr(T* p, D d = SimpleDelete<T>() ): del(d), ptr(p), counter(new uint32_t())
    {
    }

    ~shared_ptr( void )
    {
	reset();
    }

    shared_ptr( const shared_ptr& r )
    {
        ptr = r.ptr;
	counter = r.counter;
	(*counter)++;
    }

    /**
     * Reset this to 0 and decrease the usage count
     */
    void reset( void )
    {
	(*counter)--;
	if( *counter == 0 )
	{
	    del(ptr);
	    delete counter;
	    counter = 0;
	}
	ptr = 0;
    }

    T* release( void )
    {
	T* ret = ptr;
	ptr = 0;
	(*counter)--;
	if( *counter == 0 )
	{
	    delete counter;
	    counter = 0;
	}
	return ret;
    }

    shared_ptr & operator=(const shared_ptr& r)
    {
	reset();
        ptr = r.ptr;
	counter = r.counter;
	(*counter)++;
        return *this;
    }

    T& operator* () const
    {
        return *ptr;
    }

    T * operator-> () const
    {
        return ptr;
    }
    
    T * get() const
    {
        return ptr;
    }

    operator bool () const
    {
        return ptr != 0;
    }

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

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

template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b)
{
    return a._internal_less(b);
}
*/
} // namespace iwear


#endif

