Smart pointers: exclusive resource ownership

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
Post Reply
stylin
Posts: 1253
Joined: Nov 06, 2005 5:19

Smart pointers: exclusive resource ownership

Post by stylin »

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.
Post Reply