// This may look like C code, but it is really -*- C++ -*-
// 
// <copyright> 
//  
//  Copyright (c) 1994
//  Institute for Information Processing and Computer Supported New Media (IICM), 
//  Graz University of Technology, Austria. 
//  
// </copyright> 
// 
// 
// <file> 
// 
// Name:        smartptr.h
// 
// Purpose:     
// 
// Created:     12 Nov 94   Joerg Faschingbauer
// 
// Modified:    
// 
// Description: 
// 
// $Id: smartptr.h,v 1.3 1996/07/09 11:01:34 jfasch Exp $
//
// $Log: smartptr.h,v $
// Revision 1.3  1996/07/09 11:01:34  jfasch
// added the strange RefCounted::usedOnlyOnce(), which is used by the
// text viewer group (don't know why they don't use
// RefCounted::refcount() for that purpose, but ...)
//
// Revision 1.2  1996/03/01 13:53:23  jfasch
// moved from common/doccache/common to an even more common place (i.e.,
// common/utils)
//
// 
// </file> 
#ifndef hg_utils_smartptr_h
#define hg_utils_smartptr_h

#include "types.h"

// <class> 
//  
// Name:             RefCounted
// 
// Purpose:          
// 
// Public Interface: 
// 
// Description:      
// 
// </class> 
class RefCounted {
public:
   RefCounted() : refcount_(0) {}
   virtual ~RefCounted() {}

   bool usedOnlyOnce() const { return refcount_ <= 1; }
   const unsigned refcount() const { return refcount_; }

   // nops for nil pointers
   static void ref (const RefCounted*) ;
   static void unref (const RefCounted*) ;

private:
   unsigned refcount_ ;

   inline virtual void ref() const ;
   inline virtual void unref() const ;

   // deny copy
   RefCounted (const RefCounted&) {}
   RefCounted& operator =(const RefCounted&) { return *this; }
} ;
inline void RefCounted::ref() const {
    RefCounted* r = (RefCounted*) this ;
    r->refcount_ += 1 ;
}
inline void RefCounted::unref() const {
   RefCounted* r = (RefCounted*)this;
   if (r->refcount_ != 0)
      r->refcount_ -= 1 ;
   if (r->refcount_ == 0)
      delete r ;
}
inline void RefCounted::ref (const RefCounted* r) {
    if (r != nil)
	r->ref() ;
}
inline void RefCounted::unref (const RefCounted* r) {
    if (r != nil)
	r->unref() ;
}


#define SmartPtrdeclare(SmartPtr, Pointed)       \
class SmartPtr {       \
public:       \
   SmartPtr() : ptr_(nil) {}       \
   SmartPtr (Pointed*) ;       \
   SmartPtr (const SmartPtr&) ;       \
   ~SmartPtr() ;       \
          \
   SmartPtr& operator = (const SmartPtr&) ;       \
       \
   Pointed* ptr() const { return ptr_; }       \
       \
   boolean ok() const { return ptr_!=nil; }       \
   boolean operator !() const { return !ok(); }       \
   operator void*() const { return (void*)ok(); }       \
       \
   boolean operator < (const SmartPtr&) const { return false; }       \
       \
private:       \
   Pointed* ptr_ ;       \
} ;       \
inline SmartPtr& SmartPtr :: operator = (const SmartPtr& p) {       \
   RefCounted::ref (p.ptr_) ;       \
   RefCounted::unref (ptr_) ;       \
   ptr_ = p.ptr_ ;       \
   return *this ;       \
}       \
inline SmartPtr :: SmartPtr (Pointed* d)       \
: ptr_(d) {       \
   RefCounted::ref (ptr_) ;       \
}       \
inline SmartPtr :: SmartPtr (const SmartPtr& p)       \
: ptr_(nil) {       \
   operator = (p) ;       \
}       \
inline SmartPtr :: ~SmartPtr() {       \
   RefCounted::unref (ptr_) ;     \
}        \
inline class ostream& operator << (class ostream& s, const SmartPtr&) {        \
   return s ;       \
}




#endif
