Thread: A Generic Reference-Counted Pointer Class (4 Bubba)

  1. #46
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    ok, here's another variation:

    Code:
    template <class type, type set = type()>  
    struct invalid {
     invalid() 
     : value(set) {
     
      }
     inline const type & operator () (void) {
      return value;
      } 
     inline operator const type & (void) {
      return value;
      }
    protected: 
     type value;
     };
    
     template <class type, class unloader, class null_type = invalid<type, (type)0> > 
    class ref_handle {  
    public:
     inline type get (void) {
      return m_pointer;
      } 
     ref_handle & assign(ref_handle & rhs) {
      rhs.inc_ref(); /* works even if rhs == *this || rhs.m_refs == m_refs */
      dec_ref();
      m_pointer = rhs.m_pointer;
      m_refs = rhs.m_refs;
      return *this;
      }   
     inline ref_handle & operator = (ref_handle & rhs) {
      return assign(rhs);
      } 
     inline ref_handle & operator = (const ref_handle & rhs) { /* std::containers might expect this */
      return assign(const_cast<ref_handle&>(rhs));
      } 
     ref_handle & assign(type data) {
      dec_ref();
      if(data != m_null) {
       try {
        m_refs = new size_t(1); 
        } catch(std::bad_alloc & exception) { /* wow, must be serious */
        m_unload(data);
        throw exception;
        }
       m_pointer = data; 
       }
      return *this;
      }
     ref_handle & assign(type data, unloader new_unloader) {
      assign(data);
      m_unload = new_unloader;
      return *this;
      } 
     inline ref_handle & operator = (type data) {
      return assign(data);
      } 
     ref_handle(const ref_handle & rhs)
     : m_pointer(m_null), m_refs(NULL) {
      *this = rhs;
      }
     ref_handle(type data)
     : m_pointer(m_null), m_refs(NULL) {
      *this = data;
      }
     ref_handle(type data, unloader function)
     : m_pointer(m_null), m_refs(NULL), m_unload(function) {
      *this = data;
      }  
     ref_handle(void)
     : m_pointer(m_null), m_refs(NULL) {
    
      }
     virtual ~ref_handle(void) {
      dec_ref();
      } 
    protected:
     void dec_ref(void) {
      if(m_refs != NULL) {
       if(--(*m_refs) == 0) {
        m_unload(m_pointer);
        delete m_refs;    
        }
       m_pointer = m_null; 
       m_refs = NULL; 
       } 
      } 
     void inc_ref(void) {
      if(m_refs != NULL) {
       ++(*m_refs);
       }
      } 
    protected:
     type m_pointer;
     unloader m_unload;
     null_type m_null;
     size_t * m_refs;
     };  
      
     template < class type, class unloader = delete_ptr<type> >
    class ref_ptr : ref_handle < type*, unloader, invalid<type*, (type*)0> > {
    public:
     inline type * operator -> (void) {
      return m_pointer;
      } 
     inline type & operator * (void) {
      return *m_pointer;
      }
     inline ref_ptr & operator = (ref_ptr & rhs) {
      assign(rhs);  
      return *this;
      } 
     inline ref_ptr & operator = (const ref_ptr & rhs) { /* std::containers might expect this */
      assign(const_cast<ref_ptr&>(rhs));
      return *this;
      }   
     inline ref_ptr & operator = (type * data) {
      assign(data);  
      return *this;
      } 
     ref_ptr(const ref_ptr & rhs)
     : ref_handle< type*, unloader, invalid<type*, (type*)0> >(rhs) {
      
      }
     ref_ptr(type * data)
     : ref_handle< type*, unloader, invalid<type*, (type*)0> >(data) {
      
      }
     ref_ptr(type * data, unloader function)
     : ref_handle< type*, unloader, invalid<type*, (type*)0> >(data, function) {
      
      }  
     ref_ptr(void)
     : ref_handle< type*, unloader, invalid<type*, (type*)0> >() {
    
      }
     };

    the ref_handle template is for doing things like:


    Code:
    struct MsHandleCloser {
     void operator()(HANDLE handle) {
      CloseHandle(handle); 
      }
     };
    
    typedef ref_handle < HANDLE, MsHandleCloser, invalid<HANDLE, INVALID_HANDLE_VALUE> > MsHandle;



    [edit]
    the catch block had a bug - it freed 'm_pointer' instead of 'data'.
    [/edit]
    Last edited by Sebastiani; 12-19-2004 at 11:39 AM.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  2. #47
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Nice one. But the HANDLEs that are used with CloseHandle are inconsistent in their return value. Most return NULL. CreateFile returns INVALID_HANDLE_VALUE. CreateProcess returns BOOL and does not document what it sets the handles to.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Pointer to a class inside the WindowsProcedure function
    By like_no_other in forum Windows Programming
    Replies: 3
    Last Post: 06-01-2009, 12:52 PM
  2. C OpenGL Compiler Error?
    By Matt3000 in forum C Programming
    Replies: 12
    Last Post: 07-07-2006, 04:42 PM
  3. Calling a class member through a pointer to a class in a DLL
    By cboard_member in forum C++ Programming
    Replies: 1
    Last Post: 04-19-2006, 10:55 AM
  4. My Window Class
    By Epo in forum Game Programming
    Replies: 2
    Last Post: 07-10-2005, 02:33 PM
  5. qt help
    By Unregistered in forum Linux Programming
    Replies: 1
    Last Post: 04-20-2002, 09:51 AM