Smart pointers: exclusive resource ownership

Source-code only - please, don't post questions here.
stylin
Posts: 1253
Joined: Nov 06, 2005 5:19

Smart pointers: exclusive resource ownership

Postby stylin » Nov 30, 2006 14:51

This code is for CVS as of yesterday (requires public/private type fields and the NEW/DELETE operators)

Here's a port of C++'s std::auto_ptr. This type of smart pointer is useful when you need a short-lived dynamic resource. The smart pointer will destroy the pointed-to memory when it goes out of scope.

Here's the header:

Code: Select all

':: Copyright (C) 2006
'::    Laanan Fisher (stylinize@gmail.com)
':: Copyright (C) 2001, 2002, 2004
'::    Free Software Foundation, Inc.
':: Copyright (c) 1997-1999
'::    Silicon Graphics Computer Systems, Inc.

':: This file 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; either version 2, or (at your option)
':: any later version.

':: This file 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 this file; see the file COPYING.  If not, write to the Free
':: Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
':: USA.

':: As a special exception, you may use this file as part of a free software
':: library without restriction.  Specifically, if other files instantiate
':: templates or use macros or inline functions from this file, or you compile
':: this file and link it with other files to produce an executable, this
':: file does not by itself cause the resulting executable to be covered by
':: the GNU General Public License.  This exception does not however
':: invalidate any other reasons why the executable file might be covered by
':: the GNU General Public License.

/'
   auto_ptr.bi : port of C++'s std::auto_ptr
'/

# macro DECLARE_AUTO_PTR(T)
   # ifdef DECLARED_AUTO_PTR##T
   #  error auto_ptr already declared for type T
   # endif
   # define DECLARED_AUTO_PTR##T
   # ifdef DEFINED_AUTO_PTR##T
   #  error auto_ptr already defined for type T
   # endif

   /'
      A smart pointer with strict-ownership semantics.
      Resources are not allowed to be shared, an auto_ptr
      is the sole owner of it's memory - (copying an
      auto_ptr transfers ownership and invalidates the
      previous auto_ptr).
   '/
   type auto_ptr##T
   public:
      ':: Construct/Copy/Destroy/Assign
      ' Constructs an auto_ptr from a raw pointer.
      declare constructor (p as T ptr = 0)
      ' Copy constructs an auto_ptr from another.
      declare constructor (byref x as auto_ptr##T)
      ' Destroys an auto_ptr and any memory it owns.
      declare destructor ()
      ' Transfers ownership of memory from another.
      declare operator let (byref x as auto_ptr##T)

      ' Returns the address of the owned memory for lack
      ' of reference returns, identical to @*p.
      declare function derefaddr () as T ptr

      ' Returns the address of the owned memory.
      declare function get () as T ptr
      ' Releases ownership of and returns memory.
      declare function release () as T ptr
      ' Transfers ownership from another raw pointer.
      declare sub reset (p as T ptr = 0)

   private:
      ' the raw pointer.
      m_p as T ptr
   end type
# endmacro '// DECLARE_AUTO_PTR

# macro DEFINE_AUTO_PTR(T)
   # ifdef DEFINED_AUTO_PTR##T
   #  error auto_ptr already defined for type T
   # endif
   # ifndef DECLARED_AUTO_PTR##T
   DECLARE_AUTO_PTR(T)
   # endif
   # define DEFINED_AUTO_PTR##T
   
   constructor auto_ptr##T (p as T ptr)
      m_p = p
   end constructor

   constructor auto_ptr##T (byref x as auto_ptr##T)
      m_p = x.release()
   end constructor
   
   operator auto_ptr##T.let (byref x as auto_ptr##T)
      reset(x.release())
   end operator
   
   destructor auto_ptr##T ()
      ' WORKAROUND: need NULL ptr check so dtors
      ' aren't called.
      if (0 <> m_p) then
         delete m_p
      end if
   end destructor
   
   function auto_ptr##T.derefaddr () as T ptr
      ' assert enforces dereference semantics
      ASSERT( m_p <> 0 )
      function = m_p
   end function
   
   function auto_ptr##T.get () as T ptr
      function = m_p
   end function
   
   function auto_ptr##T.release () as T ptr
      dim tmp as T ptr = m_p
      m_p = 0
      function = tmp
   end function
   
   sub auto_ptr##T.reset (p as T ptr)
      if (p <> m_p) then
         ' WORKAROUND: need NULL ptr check so dtors
         ' aren't called.
         if (0 <> m_p) then
            delete m_p
         end if
         m_p = p
      end if
   end sub
# endmacro '// DEFINE_AUTO_PTR


Here's a small example:

Code: Select all

# include "auto_ptr.bi"

type T
   declare destructor ()
   member as integer
end type

destructor T ()
   print "T::~T()"
end destructor

' define auto_ptr for T types
DEFINE_AUTO_PTR(T)

   scope

      ' create an auto_ptr
      dim ap1 as auto_ptrT = new T
      
      ' dereference the auto_ptr
      ap1.derefaddr()->member = 420

      ' transfer ownership of the pointer, ap1 is now
      ' an invalid auto_ptr
      dim ap2 as auto_ptrT = ap1
      print ap2.derefaddr()->member

   end scope ' <-- mem is destroyed (once)


edit: fixed #define bug.

Return to “Tips and Tricks”

Who is online

Users browsing this forum: No registered users and 3 guests