/*
 * Copyright (c) 1999 Johnny C. Lam.
 * All rights reserved.
 *
 * Permission to use, copy, modify, distribute and sell this software
 * and its documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.  The author makes no representations
 * about the suitability of this software for any purpose.  It is
 * provided "as is" without express or implied warranty.
 */

#ifndef STL_INTERNAL_REFCOUNT_H
#define STL_INTERNAL_REFCOUNT_H

///////////////////////////////////////////////////////////////////////////
//
// Reference-counting implementation from Scott Meyers' "More Effective C++".
//
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
//
// rc_ptr
//
// Template class for smart pointers-to-T objects.  T *MUST* inherit from
// rc_object.
//
///////////////////////////////////////////////////////////////////////////

template <class T>
class rc_ptr {
public:
    rc_ptr(T* realPtr = 0 );
    rc_ptr(const rc_ptr&);
    ~rc_ptr();
    
    rc_ptr&	operator=(const rc_ptr&);
    rc_ptr&	operator=(T*);
    
    T*	operator->() const;
    T&	operator*() const;

private:
    friend bool	operator==<T> (const rc_ptr&, const rc_ptr&);
    void	init();
    
    T* _pointee;
};

///////////////////////////////////////////////////////////////////////////
//
// rc_object
//
// Abstract base class for reference-counted objects.  These objects *MUST*
// be created on the heap, and *MUST* have a deep-copying copy constructor.
// In general, these should only be manipulated through rc_ptr's.
//
///////////////////////////////////////////////////////////////////////////

class rc_object
{
public:
    void	add_reference();
    void	remove_reference();
    
    void	mark_unshareable();
    bool	is_shareable() const;
    
    bool	is_shared() const;
    
protected:
    rc_object();
    rc_object(const rc_object&);
    virtual ~rc_object() = 0;
    
    rc_object&	operator=(const rc_object&);
    
private:
    int	_refcount;
    bool _shareable;
};

#include <stl_refcount_inline.h>

#endif /* STL_INTERNAL_REFCOUNT_H */
