1080 lines
36 KiB
C++
1080 lines
36 KiB
C++
/*
|
|
Copyright (c) Microsoft Corporation
|
|
|
|
All rights reserved.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in
|
|
compliance with the License. You may obtain a copy of the License
|
|
at http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER
|
|
EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF
|
|
TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
|
|
|
|
|
|
See the Apache Version 2.0 License for specific language governing permissions and
|
|
limitations under the License.
|
|
|
|
*/
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// File: smart_any_fwd.h
|
|
//
|
|
// Contents: automatic resource management
|
|
//
|
|
// Classes: auto_any, scoped_any and shared_any
|
|
//
|
|
// Functions: get
|
|
// reset
|
|
// release
|
|
// valid
|
|
// address
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#ifndef SMART_ANY_FWD
|
|
#define SMART_ANY_FWD
|
|
|
|
#ifdef _MANAGED
|
|
#pragma warning( push )
|
|
#pragma warning( disable : 4244 )
|
|
#include <vcclr.h>
|
|
#pragma warning( pop )
|
|
|
|
#ifdef __cplusplus_cli
|
|
#define MGDHANDLE ^
|
|
#define MGDHANDLECV ^
|
|
#define MGDREFERENCE %
|
|
#else
|
|
#define MGDHANDLE __gc*
|
|
#define MGDHANDLECV const volatile__gc*
|
|
#define MGDREFERENCE __gc&
|
|
#endif
|
|
|
|
#endif
|
|
|
|
// Check to see if partial template specialization is available
|
|
#if _MSC_VER >= 1310
|
|
#define SMART_ANY_PTS
|
|
#endif
|
|
|
|
// forward declare some invalid_value policy classes
|
|
struct null_t;
|
|
|
|
template<typename T,T value = T(0)>
|
|
struct value_const;
|
|
|
|
struct close_release_com;
|
|
|
|
//
|
|
// TEMPLATE CLASS auto_any
|
|
//
|
|
template<typename T,class close_policy,class invalid_value = null_t,int unique = 0>
|
|
class auto_any;
|
|
|
|
// return wrapped resource
|
|
template<typename T,class close_policy,class invalid_value,int unique>
|
|
T get( auto_any<T,close_policy,invalid_value,unique> const & t );
|
|
|
|
// return true if the auto_any contains a currently valid resource
|
|
template<typename T,class close_policy,class invalid_value,int unique>
|
|
bool valid( auto_any<T,close_policy,invalid_value,unique> const & t );
|
|
|
|
// return wrapped resource and give up ownership
|
|
template<typename T,class close_policy,class invalid_value,int unique>
|
|
T release( auto_any<T,close_policy,invalid_value, unique> & t );
|
|
|
|
// destroy designated object
|
|
template<typename T,class close_policy,class invalid_value,int unique>
|
|
void reset( auto_any<T,close_policy,invalid_value,unique> & t );
|
|
|
|
// destroy designated object and store new resource
|
|
template<typename T,class close_policy,class invalid_value,int unique,typename U>
|
|
void reset( auto_any<T,close_policy,invalid_value,unique> & t, U newT );
|
|
|
|
// swap the contents of two shared_any objects
|
|
template<typename T,class close_policy,class invalid_value,int unique>
|
|
void swap( auto_any<T,close_policy,invalid_value,unique> & left,
|
|
auto_any<T,close_policy,invalid_value,unique> & right );
|
|
|
|
// return the address of the wrapped resource
|
|
// WARNING: this will assert if the value of the resource is
|
|
// anything other than invalid_value.
|
|
//template<typename T,class close_policy,class invalid_value,int unique>
|
|
//T* address( auto_any<T,close_policy,invalid_value,unique> & t );
|
|
|
|
//
|
|
// TEMPLATE CLASS shared_any
|
|
//
|
|
template<typename T,class close_policy,class invalid_value = null_t,int unique = 0>
|
|
class shared_any;
|
|
|
|
// return wrapped resource
|
|
template<typename T,class close_policy,class invalid_value,int unique>
|
|
T get( shared_any<T,close_policy,invalid_value,unique> const & t );
|
|
|
|
// return true if the auto_any contains a currently valid resource
|
|
template<typename T,class close_policy,class invalid_value,int unique>
|
|
bool valid( shared_any<T,close_policy,invalid_value,unique> const & t );
|
|
|
|
// destroy designated object
|
|
template<typename T,class close_policy,class invalid_value,int unique>
|
|
void reset( shared_any<T,close_policy,invalid_value,unique> & t );
|
|
|
|
// destroy designated object and store new resource
|
|
template<typename T,class close_policy,class invalid_value,int unique,typename U>
|
|
void reset( shared_any<T,close_policy,invalid_value,unique> & t, U newT );
|
|
|
|
// swap the contents of two shared_any objects
|
|
template<typename T,class close_policy,class invalid_value,int unique>
|
|
void swap( shared_any<T,close_policy,invalid_value,unique> & left,
|
|
shared_any<T,close_policy,invalid_value,unique> & right );
|
|
|
|
|
|
//
|
|
// TEMPLATE CLASS scoped_any
|
|
//
|
|
template<typename T,class close_policy,class invalid_value = null_t,int unique = 0>
|
|
class scoped_any;
|
|
|
|
// return wrapped resource
|
|
template<typename T,class close_policy,class invalid_value,int unique>
|
|
T get( scoped_any<T,close_policy,invalid_value,unique> const & t );
|
|
|
|
// return true if the auto_any contains a currently valid resource
|
|
template<typename T,class close_policy,class invalid_value,int unique>
|
|
bool valid( scoped_any<T,close_policy,invalid_value,unique> const & t );
|
|
|
|
// return wrapped resource and give up ownership
|
|
template<typename T,class close_policy,class invalid_value,int unique>
|
|
T release( scoped_any<T,close_policy,invalid_value, unique> & t );
|
|
|
|
// destroy designated object
|
|
template<typename T,class close_policy,class invalid_value,int unique>
|
|
void reset( scoped_any<T,close_policy,invalid_value,unique> & t );
|
|
|
|
// destroy designated object and store new resource
|
|
template<typename T,class close_policy,class invalid_value,int unique,typename U>
|
|
void reset( scoped_any<T,close_policy,invalid_value,unique> & t, U newT );
|
|
|
|
// return the address of the wrapped resource
|
|
// WARNING: this will assert if the value of the resource is
|
|
// anything other than invalid_value.
|
|
//template<typename T,class close_policy,class invalid_value,int unique>
|
|
//T* address( scoped_any<T,close_policy,invalid_value,unique> & t );
|
|
|
|
// close policy for objects allocated with new
|
|
struct close_delete;
|
|
|
|
namespace detail
|
|
{
|
|
typedef char (&yes)[1];
|
|
typedef char (&no) [2];
|
|
|
|
struct dummy_struct
|
|
{
|
|
void dummy_method() {}
|
|
};
|
|
|
|
typedef void (dummy_struct::*safe_bool)();
|
|
safe_bool const safe_true = &dummy_struct::dummy_method;
|
|
safe_bool const safe_false = 0;
|
|
|
|
// Because of older compilers, we can't always use
|
|
// null_t when we would like to.
|
|
template<class invalid_value>
|
|
struct fixup_invalid_value
|
|
{
|
|
template<typename> struct rebind { typedef invalid_value type; };
|
|
};
|
|
|
|
// for compile-time assertions
|
|
template<bool>
|
|
struct static_assert;
|
|
|
|
template<>
|
|
struct static_assert<true>
|
|
{
|
|
static_assert() {}
|
|
};
|
|
|
|
template<typename T>
|
|
struct static_init
|
|
{
|
|
static T const value;
|
|
};
|
|
|
|
template<typename T>
|
|
T const static_init<T>::value = T();
|
|
|
|
template<bool>
|
|
struct null_helper // unmanaged
|
|
{
|
|
template<typename T>
|
|
struct inner
|
|
{
|
|
static T const get()
|
|
{
|
|
return static_init<T>::value;
|
|
}
|
|
};
|
|
};
|
|
|
|
template<>
|
|
struct null_helper<true> // managed
|
|
{
|
|
template<typename T>
|
|
struct inner
|
|
{
|
|
static T const get()
|
|
{
|
|
return 0;
|
|
}
|
|
};
|
|
};
|
|
|
|
template<bool>
|
|
struct select_helper
|
|
{
|
|
template<typename T,typename>
|
|
struct inner { typedef T type; };
|
|
};
|
|
|
|
template<>
|
|
struct select_helper<false>
|
|
{
|
|
template<typename,typename U>
|
|
struct inner { typedef U type; };
|
|
};
|
|
|
|
template<bool F,typename T,typename U>
|
|
struct select
|
|
{
|
|
typedef typename select_helper<F>::template inner<T,U>::type type;
|
|
};
|
|
|
|
|
|
template< bool >
|
|
struct holder_helper
|
|
{
|
|
template<typename T>
|
|
struct inner
|
|
{
|
|
typedef T type;
|
|
};
|
|
};
|
|
|
|
template< typename T >
|
|
struct remove_ref
|
|
{
|
|
typedef T type;
|
|
};
|
|
|
|
#ifdef SMART_ANY_PTS
|
|
template< typename T >
|
|
struct remove_ref<T&>
|
|
{
|
|
typedef T type;
|
|
};
|
|
#endif
|
|
|
|
template<typename T>
|
|
T* address_of( T & v )
|
|
{
|
|
return reinterpret_cast<T*>(
|
|
&const_cast<char&>(
|
|
reinterpret_cast<char const volatile &>(v)));
|
|
}
|
|
|
|
#ifndef _MANAGED
|
|
|
|
template<typename T>
|
|
struct is_managed
|
|
{
|
|
static bool const value = false;
|
|
};
|
|
|
|
#else
|
|
|
|
struct managed_convertible
|
|
{
|
|
managed_convertible( System::Object MGDHANDLECV );
|
|
managed_convertible( System::Enum MGDHANDLECV );
|
|
managed_convertible( System::ValueType MGDHANDLECV );
|
|
managed_convertible( System::Delegate MGDHANDLECV );
|
|
};
|
|
|
|
template<typename T>
|
|
struct is_managed
|
|
{
|
|
private:
|
|
static yes check( managed_convertible );
|
|
static no __cdecl check( ... );
|
|
static typename remove_ref<T>::type & make();
|
|
public:
|
|
static bool const value = sizeof( yes ) == sizeof( check( make() ) );
|
|
};
|
|
|
|
#ifdef SMART_ANY_PTS
|
|
template<typename T>
|
|
struct is_managed<T MGDREFERENCE>
|
|
{
|
|
static bool const value = true;
|
|
};
|
|
template<typename T>
|
|
struct is_managed<T MGDHANDLE>
|
|
{
|
|
static bool const value = true;
|
|
};
|
|
template<typename T>
|
|
struct is_managed<T MGDHANDLE const>
|
|
{
|
|
static bool const value = is_managed<T MGDHANDLE>::value;
|
|
};
|
|
template<typename T>
|
|
struct is_managed<T MGDHANDLE volatile>
|
|
{
|
|
static bool const value = is_managed<T MGDHANDLE>::value;
|
|
};
|
|
template<typename T>
|
|
struct is_managed<T MGDHANDLE const volatile>
|
|
{
|
|
static bool const value = is_managed<T MGDHANDLE>::value;
|
|
};
|
|
#endif
|
|
#ifndef __cplusplus_cli
|
|
template<>
|
|
struct is_managed<System::Void MGDHANDLE>
|
|
{
|
|
static bool const value = true;
|
|
};
|
|
template<>
|
|
struct is_managed<System::Void const MGDHANDLE>
|
|
{
|
|
static bool const value = true;
|
|
};
|
|
template<>
|
|
struct is_managed<System::Void volatile MGDHANDLE>
|
|
{
|
|
static bool const value = true;
|
|
};
|
|
template<>
|
|
struct is_managed<System::Void const volatile MGDHANDLE>
|
|
{
|
|
static bool const value = true;
|
|
};
|
|
#endif
|
|
|
|
template<>
|
|
struct holder_helper<true>
|
|
{
|
|
template<typename T>
|
|
struct inner
|
|
{
|
|
typedef gcroot<T> type;
|
|
};
|
|
};
|
|
#endif
|
|
|
|
template<typename T>
|
|
struct holder
|
|
{
|
|
typedef typename holder_helper<is_managed<T>::value>::template inner<T>::type type;
|
|
};
|
|
|
|
template<typename T>
|
|
struct is_delete
|
|
{
|
|
static bool const value = false;
|
|
};
|
|
|
|
template<>
|
|
struct is_delete<close_delete>
|
|
{
|
|
static bool const value = true;
|
|
};
|
|
|
|
// dummy type, don't define
|
|
struct smart_any_cannot_dereference;
|
|
|
|
// For use in implementing unary operator*
|
|
template<typename T>
|
|
struct deref
|
|
{
|
|
typedef smart_any_cannot_dereference type; // will cause a compile error by default
|
|
};
|
|
|
|
#ifndef SMART_ANY_PTS
|
|
|
|
// Old compiler needs extra help
|
|
template<>
|
|
struct fixup_invalid_value<null_t>
|
|
{
|
|
template<typename T> struct rebind { typedef value_const<T> type; };
|
|
};
|
|
|
|
#else
|
|
|
|
template<typename T,typename U>
|
|
struct same_type
|
|
{
|
|
static const int value = false;
|
|
};
|
|
|
|
template<typename T>
|
|
struct same_type<T,T>
|
|
{
|
|
static const int value = true;
|
|
};
|
|
|
|
// Handle reference types
|
|
template<typename T>
|
|
struct deref<T&>
|
|
{
|
|
typedef typename deref<T>::type type;
|
|
};
|
|
|
|
// Partially specialize for pointer types
|
|
template<typename T>
|
|
struct deref<T*>
|
|
{
|
|
typedef T& type; // The result of dereferencing a T*
|
|
};
|
|
|
|
// Partially specialize for pointer types
|
|
template<typename T>
|
|
struct deref<T*const>
|
|
{
|
|
typedef typename deref<T*>::type type; // The result of dereferencing a T*
|
|
};
|
|
|
|
// Partially specialize for pointer types
|
|
template<typename T>
|
|
struct deref<T*volatile>
|
|
{
|
|
typedef typename deref<T*>::type type; // The result of dereferencing a T*
|
|
};
|
|
|
|
// Partially specialize for pointer types
|
|
template<typename T>
|
|
struct deref<T*const volatile>
|
|
{
|
|
typedef typename deref<T*>::type type; // The result of dereferencing a T*
|
|
};
|
|
|
|
// Fully specialize for void*
|
|
template<>
|
|
struct deref<void*>
|
|
{
|
|
typedef smart_any_cannot_dereference type; // cannot dereference a void*
|
|
};
|
|
|
|
// Fully specialize for void const*
|
|
template<>
|
|
struct deref<void const*>
|
|
{
|
|
typedef smart_any_cannot_dereference type; // cannot dereference a void*
|
|
};
|
|
|
|
// Fully specialize for void volatile*
|
|
template<>
|
|
struct deref<void volatile*>
|
|
{
|
|
typedef smart_any_cannot_dereference type; // cannot dereference a void*
|
|
};
|
|
|
|
// Fully specialize for void const volatile*
|
|
template<>
|
|
struct deref<void const volatile*>
|
|
{
|
|
typedef smart_any_cannot_dereference type; // cannot dereference a void*
|
|
};
|
|
|
|
#ifdef _MANAGED
|
|
// Handle reference types
|
|
template<typename T>
|
|
struct deref<T MGDREFERENCE>
|
|
{
|
|
typedef typename deref<T>::type type;
|
|
};
|
|
|
|
// Partially specialize for pointer types
|
|
template<typename T>
|
|
struct deref<T MGDHANDLE>
|
|
{
|
|
typedef T MGDREFERENCE type; // The result of dereferencing a T MGDHANDLE
|
|
};
|
|
|
|
// Partially specialize for pointer types
|
|
template<typename T>
|
|
struct deref<T MGDHANDLE const>
|
|
{
|
|
typedef typename deref<T MGDHANDLE>::type type; // The result of dereferencing a T MGDHANDLE
|
|
};
|
|
|
|
// Partially specialize for pointer types
|
|
template<typename T>
|
|
struct deref<T MGDHANDLE volatile>
|
|
{
|
|
typedef typename deref<T MGDHANDLE>::type type; // The result of dereferencing a T MGDHANDLE
|
|
};
|
|
|
|
// Partially specialize for pointer types
|
|
template<typename T>
|
|
struct deref<T MGDHANDLE const volatile>
|
|
{
|
|
typedef typename deref<T MGDHANDLE>::type type; // The result of dereferencing a T MGDHANDLE
|
|
};
|
|
|
|
#ifndef __cplusplus_cli
|
|
// Fully specialize for void*
|
|
template<>
|
|
struct deref<System::Void MGDHANDLE>
|
|
{
|
|
typedef smart_any_cannot_dereference type; // cannot dereference a System::Void MGDHANDLE
|
|
};
|
|
|
|
// Fully specialize for void const*
|
|
template<>
|
|
struct deref<System::Void const MGDHANDLE>
|
|
{
|
|
typedef smart_any_cannot_dereference type; // cannot dereference a System::Void MGDHANDLE
|
|
};
|
|
|
|
// Fully specialize for void volatile*
|
|
template<>
|
|
struct deref<System::Void volatile MGDHANDLE>
|
|
{
|
|
typedef smart_any_cannot_dereference type; // cannot dereference a System::Void MGDHANDLE
|
|
};
|
|
|
|
// Fully specialize for void const volatile*
|
|
template<>
|
|
struct deref<System::Void const volatile MGDHANDLE>
|
|
{
|
|
typedef smart_any_cannot_dereference type; // cannot dereference a System::Void MGDHANDLE
|
|
};
|
|
#endif // __cplusplus_cli
|
|
#endif
|
|
|
|
// The DECLARE_HANDLE macro in winnt.h defines a handle to be a pointer
|
|
// to a struct containing one member named "unused" of type int. We can
|
|
// use that information to make auto_any safer by disallowing actions like
|
|
// dereferencing a handle or calling delete on a handle.
|
|
template<typename T>
|
|
struct has_unused
|
|
{
|
|
private:
|
|
template<class U,int U::*> struct wrap_t;
|
|
template<typename U> static yes check( wrap_t<U,&U::unused>* );
|
|
template<typename U> static no __cdecl check( ... );
|
|
public:
|
|
static bool const value = ( sizeof(check<T>(0)) == sizeof(yes) );
|
|
};
|
|
|
|
template<typename T>
|
|
struct is_handle_helper
|
|
{
|
|
static bool const value = ( sizeof(T)==sizeof(int) && has_unused<T>::value );
|
|
};
|
|
|
|
#ifdef _MANAGED
|
|
template<typename T>
|
|
struct is_handle_helper<T MGDREFERENCE>
|
|
{
|
|
static bool const value = false;
|
|
};
|
|
#endif
|
|
|
|
template<>
|
|
struct is_handle_helper<smart_any_cannot_dereference>
|
|
{
|
|
static bool const value = false;
|
|
};
|
|
|
|
// used to see whether a given type T is a handle type or not.
|
|
template<typename T>
|
|
struct is_handle
|
|
{
|
|
private:
|
|
typedef typename remove_ref<typename deref<T>::type>::type deref_t;
|
|
public:
|
|
static bool const value =
|
|
( same_type<T,void*>::value || is_handle_helper<deref_t>::value );
|
|
};
|
|
#endif
|
|
|
|
template<typename T,class close_policy>
|
|
struct safe_types
|
|
{
|
|
typedef T pointer_type;
|
|
typedef typename deref<T>::type reference_type;
|
|
|
|
static pointer_type to_pointer( T t )
|
|
{
|
|
return t;
|
|
}
|
|
static reference_type to_reference( T t )
|
|
{
|
|
return *t;
|
|
}
|
|
};
|
|
|
|
#ifdef SMART_ANY_PTS
|
|
template<typename T>
|
|
class no_addref_release : public T
|
|
{
|
|
unsigned long __stdcall AddRef();
|
|
unsigned long __stdcall Release();
|
|
};
|
|
|
|
// shouldn't be able to call AddRef or Release
|
|
// through a smart COM wrapper
|
|
template<typename T>
|
|
struct safe_types<T*,close_release_com>
|
|
{
|
|
typedef no_addref_release<T>* pointer_type;
|
|
typedef no_addref_release<T>& reference_type;
|
|
|
|
static pointer_type to_pointer( T* t )
|
|
{
|
|
return static_cast<pointer_type>( t );
|
|
}
|
|
static reference_type to_reference( T* t )
|
|
{
|
|
return *static_cast<pointer_type>( t );
|
|
}
|
|
};
|
|
#endif
|
|
}
|
|
|
|
// a generic close policy that uses a ptr to a function
|
|
template<typename Fn, Fn Pfn>
|
|
struct close_fun
|
|
{
|
|
template<typename T>
|
|
static void close( T t )
|
|
{
|
|
Pfn( t );
|
|
}
|
|
};
|
|
|
|
// free an object allocated with new by calling delete
|
|
struct close_delete
|
|
{
|
|
template<typename T>
|
|
static void close( T * p )
|
|
{
|
|
// This will fail only if T is an incomplete type.
|
|
static detail::static_assert<0 != sizeof( T )> const cannot_delete_an_incomplete_type;
|
|
|
|
#ifdef SMART_ANY_PTS
|
|
// This checks to make sure we're not calling delete on a HANDLE
|
|
static detail::static_assert<!detail::is_handle<T*>::value> const cannot_delete_a_handle;
|
|
#endif
|
|
|
|
delete p;
|
|
}
|
|
|
|
#ifdef _MANAGED
|
|
template<typename T>
|
|
static void close( gcroot<T MGDHANDLE> const & p )
|
|
{
|
|
delete static_cast<T MGDHANDLE>( p );
|
|
}
|
|
#endif
|
|
};
|
|
|
|
// free an array allocated with new[] by calling delete[]
|
|
struct close_delete_array
|
|
{
|
|
template<typename T>
|
|
static void close( T * p )
|
|
{
|
|
// This will fail only if T is an incomplete type.
|
|
static detail::static_assert<0 != sizeof( T )> const cannot_delete_an_incomplete_type;
|
|
|
|
#ifdef SMART_ANY_PTS
|
|
// This checks to make sure we're not calling delete on a HANDLE
|
|
static detail::static_assert<!detail::is_handle<T*>::value> const cannot_delete_a_handle;
|
|
#endif
|
|
|
|
delete [] p;
|
|
}
|
|
|
|
//#ifdef _MANAGED
|
|
// This is broken because of compiler bugs
|
|
//template<typename T>
|
|
//static void close( gcroot<T __gc* __gc[]> const & p )
|
|
//{
|
|
// delete [] static_cast<T __gc* __gc[]>( p );
|
|
//}
|
|
//#endif
|
|
};
|
|
|
|
// for releasing a COM object
|
|
struct close_release_com
|
|
{
|
|
template<typename T>
|
|
static void close( T p )
|
|
{
|
|
p->Release();
|
|
}
|
|
};
|
|
|
|
// for releasing a __gc IDisposable object
|
|
struct close_dispose
|
|
{
|
|
template<typename T>
|
|
static void close( T p )
|
|
{
|
|
p->Dispose();
|
|
}
|
|
};
|
|
|
|
// some generic invalid_value policies
|
|
|
|
struct null_t
|
|
{
|
|
template<typename T>
|
|
operator T const() const
|
|
{
|
|
return detail::null_helper<detail::is_managed<T>::value>::template inner<T>::get();
|
|
}
|
|
};
|
|
|
|
template<typename T,T value>
|
|
struct value_const
|
|
{
|
|
operator T const() const
|
|
{
|
|
return value;
|
|
}
|
|
};
|
|
|
|
template<typename T,T const* value_ptr>
|
|
struct value_const_ptr
|
|
{
|
|
operator T const&() const
|
|
{
|
|
return *value_ptr;
|
|
}
|
|
};
|
|
|
|
#ifdef SMART_ANY_PTS
|
|
template<typename T, T const& value>
|
|
struct value_ref
|
|
{
|
|
operator T const&() const
|
|
{
|
|
return value;
|
|
}
|
|
};
|
|
#endif
|
|
|
|
#endif // SMART_ANY_FWD
|
|
|
|
|
|
//
|
|
// Define some other useful close polcies
|
|
//
|
|
|
|
#if defined(_INC_STDLIB) | defined(_INC_MALLOC)
|
|
typedef void (__cdecl *pfn_free_t)( void* );
|
|
typedef close_fun<pfn_free_t,static_cast<pfn_free_t>(&free)> close_free;
|
|
#endif
|
|
|
|
#if defined(_INC_STDIO) & !defined(SMART_CLOSE_FILE_PTR)
|
|
# define SMART_CLOSE_FILE_PTR
|
|
// don't close a FILE* if it is stdin, stdout or stderr
|
|
struct close_file_ptr
|
|
{
|
|
static void close( FILE * pfile )
|
|
{
|
|
if( pfile != stdin && pfile != stdout && pfile != stderr )
|
|
{
|
|
fclose( pfile );
|
|
}
|
|
}
|
|
};
|
|
#endif
|
|
|
|
#ifdef _WINDOWS_
|
|
|
|
# ifndef SMART_VIRTUAL_FREE
|
|
# define SMART_VIRTUAL_FREE
|
|
// free memory allocated with VirtualAlloc
|
|
struct close_virtual_free
|
|
{
|
|
static void close( void * p )
|
|
{
|
|
::VirtualFree( p, 0, MEM_RELEASE );
|
|
}
|
|
};
|
|
# endif
|
|
|
|
typedef close_fun<BOOL (__stdcall *)( HANDLE ),CloseHandle> close_handle;
|
|
typedef close_fun<BOOL (__stdcall *)( HANDLE ),FindClose> close_find;
|
|
typedef close_fun<BOOL (__stdcall *)( HINSTANCE ),FreeLibrary> close_library;
|
|
typedef close_fun<LONG (__stdcall *)( HKEY ),RegCloseKey> close_regkey;
|
|
typedef close_fun<BOOL (__stdcall *)( LPCVOID ),UnmapViewOfFile> close_file_view;
|
|
typedef close_fun<BOOL (__stdcall *)( HICON ),DestroyIcon> close_hicon;
|
|
typedef close_fun<BOOL (__stdcall *)( HGDIOBJ ),DeleteObject> close_hgdiobj;
|
|
typedef close_fun<BOOL (__stdcall *)( HACCEL ),DestroyAcceleratorTable> close_haccel;
|
|
typedef close_fun<BOOL (__stdcall *)( HDC ),DeleteDC> close_hdc;
|
|
typedef close_fun<BOOL (__stdcall *)( HMENU ),DestroyMenu> close_hmenu;
|
|
typedef close_fun<BOOL (__stdcall *)( HCURSOR ),DestroyCursor> close_hcursor;
|
|
typedef close_fun<BOOL (__stdcall *)( HWND ),DestroyWindow> close_window;
|
|
typedef close_fun<BOOL (__stdcall *)( HANDLE ),HeapDestroy> close_heap_destroy;
|
|
typedef close_fun<HLOCAL (__stdcall *)( HLOCAL ),LocalFree> close_local_free;
|
|
typedef close_fun<BOOL (__stdcall *)( HDESK ),CloseDesktop> close_hdesk;
|
|
typedef close_fun<BOOL (__stdcall *)( HHOOK ),UnhookWindowsHookEx> close_hhook;
|
|
typedef close_fun<BOOL (__stdcall *)( HWINSTA ),CloseWindowStation> close_hwinsta;
|
|
typedef close_fun<BOOL (__stdcall *)( HANDLE ),DeregisterEventSource> close_event_source;
|
|
typedef close_fun<HGLOBAL (__stdcall *)( HGLOBAL ),GlobalFree> close_global_free;
|
|
|
|
typedef value_const<HANDLE,INVALID_HANDLE_VALUE> invalid_handle_t;
|
|
#endif
|
|
|
|
#ifdef _OLEAUTO_H_
|
|
typedef close_fun<void (__stdcall *)(BSTR),SysFreeString> close_bstr;
|
|
#endif
|
|
|
|
#ifdef __MSGQUEUE_H__
|
|
typedef close_fun<BOOL (__stdcall *)(HANDLE),CloseMsgQueue> close_msg_queue;
|
|
#endif
|
|
|
|
#if defined(_WININET_) | defined(_DUBINET_)
|
|
typedef close_fun<BOOL (__stdcall *)(HINTERNET),InternetCloseHandle> close_hinternet;
|
|
#endif
|
|
|
|
#ifdef _RAS_H_
|
|
typedef close_fun<DWORD (__stdcall *)( HRASCONN ),RasHangUp> close_hrasconn;
|
|
#endif
|
|
|
|
#if defined(__RPCDCE_H__) & !defined(SMART_ANY_RPC)
|
|
# define SMART_ANY_RPC
|
|
// for releaseing an rpc binding
|
|
struct close_rpc_binding
|
|
{
|
|
static void close( RPC_BINDING_HANDLE & h )
|
|
{
|
|
::RpcBindingFree( &h );
|
|
}
|
|
};
|
|
// for releaseing an rpc binding vector
|
|
struct close_rpc_vector
|
|
{
|
|
static void close( RPC_BINDING_VECTOR __RPC_FAR * & p )
|
|
{
|
|
::RpcBindingVectorFree( &p );
|
|
}
|
|
};
|
|
// for releasing a RPC string
|
|
struct close_rpc_string
|
|
{
|
|
static void close( unsigned char __RPC_FAR * & p )
|
|
{
|
|
::RpcStringFreeA(&p);
|
|
}
|
|
static void close( unsigned short __RPC_FAR * & p )
|
|
{
|
|
::RpcStringFreeW(&p);
|
|
}
|
|
};
|
|
#endif
|
|
|
|
#ifdef _WINSVC_
|
|
typedef close_fun<BOOL (__stdcall *)( SC_HANDLE ),CloseServiceHandle> close_service;
|
|
typedef close_fun<BOOL (__stdcall *)( SC_LOCK ),UnlockServiceDatabase> unlock_service;
|
|
#endif
|
|
|
|
#ifdef _WINSOCKAPI_
|
|
typedef int (__stdcall *pfn_closock_t)( SOCKET );
|
|
typedef close_fun<pfn_closock_t,static_cast<pfn_closock_t>(&closesocket)> close_socket;
|
|
typedef value_const<SOCKET,INVALID_SOCKET> invalid_socket_t;
|
|
#endif
|
|
|
|
#ifdef _OBJBASE_H_
|
|
// For use when releasing memory allocated with CoTaskMemAlloc
|
|
typedef close_fun<void (__stdcall*)( LPVOID ),CoTaskMemFree> close_co_task_free;
|
|
#endif
|
|
|
|
|
|
//
|
|
// Below are useful smart typedefs for some common Windows/CRT resource types.
|
|
//
|
|
|
|
#undef DECLARE_SMART_ANY_TYPEDEFS_STDIO
|
|
#undef DECLARE_SMART_ANY_TYPEDEFS_WINDOWS
|
|
#undef DECLARE_SMART_ANY_TYPEDEFS_OLEAUTO
|
|
#undef DECLARE_SMART_ANY_TYPEDEFS_MSGQUEUE
|
|
#undef DECLARE_SMART_ANY_TYPEDEFS_WININET
|
|
#undef DECLARE_SMART_ANY_TYPEDEFS_RAS
|
|
#undef DECLARE_SMART_ANY_TYPEDEFS_RPCDCE
|
|
#undef DECLARE_SMART_ANY_TYPEDEFS_WINSVC
|
|
#undef DECLARE_SMART_ANY_TYPEDEFS_WINSOCKAPI
|
|
#undef DECLARE_SMART_ANY_TYPEDEFS_OBJBASE
|
|
|
|
#define DECLARE_SMART_ANY_TYPEDEFS_STDIO(prefix)
|
|
#define DECLARE_SMART_ANY_TYPEDEFS_WINDOWS(prefix)
|
|
#define DECLARE_SMART_ANY_TYPEDEFS_OLEAUTO(prefix)
|
|
#define DECLARE_SMART_ANY_TYPEDEFS_MSGQUEUE(prefix)
|
|
#define DECLARE_SMART_ANY_TYPEDEFS_WININET(prefix)
|
|
#define DECLARE_SMART_ANY_TYPEDEFS_RAS(prefix)
|
|
#define DECLARE_SMART_ANY_TYPEDEFS_RPCDCE(prefix)
|
|
#define DECLARE_SMART_ANY_TYPEDEFS_WINSVC(prefix)
|
|
#define DECLARE_SMART_ANY_TYPEDEFS_WINSOCKAPI(prefix)
|
|
#define DECLARE_SMART_ANY_TYPEDEFS_OBJBASE(prefix)
|
|
|
|
#ifdef _INC_STDIO
|
|
# undef DECLARE_SMART_ANY_TYPEDEFS_STDIO
|
|
# define DECLARE_SMART_ANY_TYPEDEFS_STDIO(prefix) \
|
|
typedef prefix ## _any<FILE*,close_file_ptr> prefix ## _file_ptr;
|
|
#endif
|
|
|
|
#ifdef _WINDOWS_
|
|
# undef DECLARE_SMART_ANY_TYPEDEFS_WINDOWS
|
|
# define DECLARE_SMART_ANY_TYPEDEFS_WINDOWS(prefix) \
|
|
typedef prefix ## _any<HKEY,close_regkey> prefix ## _hkey; \
|
|
typedef prefix ## _any<HANDLE,close_find,invalid_handle_t> prefix ## _hfind; \
|
|
typedef prefix ## _any<HANDLE,close_handle,invalid_handle_t> prefix ## _hfile; \
|
|
typedef prefix ## _any<HANDLE,close_handle,invalid_handle_t,1> prefix ## _communications_device; \
|
|
typedef prefix ## _any<HANDLE,close_handle,invalid_handle_t,2> prefix ## _console_input; \
|
|
typedef prefix ## _any<HANDLE,close_handle,invalid_handle_t,3> prefix ## _console_input_buffer; \
|
|
typedef prefix ## _any<HANDLE,close_handle,invalid_handle_t,4> prefix ## _console_output; \
|
|
typedef prefix ## _any<HANDLE,close_handle,invalid_handle_t,5> prefix ## _mailslot; \
|
|
typedef prefix ## _any<HANDLE,close_handle,invalid_handle_t,6> prefix ## _pipe; \
|
|
typedef prefix ## _any<HANDLE,close_handle> prefix ## _handle; \
|
|
typedef prefix ## _any<HANDLE,close_handle,null_t,1> prefix ## _access_token; \
|
|
typedef prefix ## _any<HANDLE,close_handle,null_t,2> prefix ## _event; \
|
|
typedef prefix ## _any<HANDLE,close_handle,null_t,3> prefix ## _file_mapping; \
|
|
typedef prefix ## _any<HANDLE,close_handle,null_t,4> prefix ## _job; \
|
|
typedef prefix ## _any<HANDLE,close_handle,null_t,5> prefix ## _mutex; \
|
|
typedef prefix ## _any<HANDLE,close_handle,null_t,6> prefix ## _process; \
|
|
typedef prefix ## _any<HANDLE,close_handle,null_t,7> prefix ## _semaphore; \
|
|
typedef prefix ## _any<HANDLE,close_handle,null_t,8> prefix ## _thread; \
|
|
typedef prefix ## _any<HANDLE,close_handle,null_t,9> prefix ## _timer; \
|
|
typedef prefix ## _any<HANDLE,close_handle,null_t,10> prefix ## _completion_port; \
|
|
typedef prefix ## _any<HDC,close_hdc> prefix ## _hdc; \
|
|
typedef prefix ## _any<HICON,close_hicon> prefix ## _hicon; \
|
|
typedef prefix ## _any<HMENU,close_hmenu> prefix ## _hmenu; \
|
|
typedef prefix ## _any<HCURSOR,close_hcursor> prefix ## _hcursor; \
|
|
typedef prefix ## _any<HPEN,close_hgdiobj,null_t,1> prefix ## _hpen; \
|
|
typedef prefix ## _any<HRGN,close_hgdiobj,null_t,2> prefix ## _hrgn; \
|
|
typedef prefix ## _any<HFONT,close_hgdiobj,null_t,3> prefix ## _hfont; \
|
|
typedef prefix ## _any<HBRUSH,close_hgdiobj,null_t,4> prefix ## _hbrush; \
|
|
typedef prefix ## _any<HBITMAP,close_hgdiobj,null_t,5> prefix ## _hbitmap; \
|
|
typedef prefix ## _any<HPALETTE,close_hgdiobj,null_t,6> prefix ## _hpalette; \
|
|
typedef prefix ## _any<HACCEL,close_haccel> prefix ## _haccel; \
|
|
typedef prefix ## _any<HWND,close_window> prefix ## _window; \
|
|
typedef prefix ## _any<HINSTANCE,close_library> prefix ## _library; \
|
|
typedef prefix ## _any<LPVOID,close_file_view> prefix ## _file_view; \
|
|
typedef prefix ## _any<LPVOID,close_virtual_free> prefix ## _virtual_ptr; \
|
|
typedef prefix ## _any<HANDLE,close_heap_destroy> prefix ## _heap; \
|
|
typedef prefix ## _any<HLOCAL,close_local_free> prefix ## _hlocal; \
|
|
typedef prefix ## _any<HDESK,close_hdesk> prefix ## _hdesk; \
|
|
typedef prefix ## _any<HHOOK,close_hhook> prefix ## _hhook; \
|
|
typedef prefix ## _any<HWINSTA,close_hwinsta> prefix ## _hwinsta; \
|
|
typedef prefix ## _any<HANDLE,close_event_source> prefix ## _event_source; \
|
|
typedef prefix ## _any<HGLOBAL,close_global_free> prefix ## _hglobal;
|
|
#endif
|
|
|
|
//
|
|
// Define some other useful typedefs
|
|
//
|
|
|
|
#ifdef _OLEAUTO_H_
|
|
# undef DECLARE_SMART_ANY_TYPEDEFS_OLEAUTO
|
|
# define DECLARE_SMART_ANY_TYPEDEFS_OLEAUTO(prefix) \
|
|
typedef prefix ## _any<BSTR,close_bstr> prefix ## _bstr;
|
|
#endif
|
|
|
|
#ifdef __MSGQUEUE_H__
|
|
# undef DECLARE_SMART_ANY_TYPEDEFS_MSGQUEUE
|
|
# define DECLARE_SMART_ANY_TYPEDEFS_MSGQUEUE(prefix) \
|
|
typedef prefix ## _any<HANDLE,close_msg_queue> prefix ## _msg_queue;
|
|
#endif
|
|
|
|
#if defined(_WININET_) | defined(_DUBINET_)
|
|
# undef DECLARE_SMART_ANY_TYPEDEFS_WININET
|
|
# define DECLARE_SMART_ANY_TYPEDEFS_WININET(prefix) \
|
|
typedef prefix ## _any<HINTERNET,close_hinternet> prefix ## _hinternet;
|
|
#endif
|
|
|
|
#ifdef _RAS_H_
|
|
# undef DECLARE_SMART_ANY_TYPEDEFS_RAS
|
|
# define DECLARE_SMART_ANY_TYPEDEFS_RAS(prefix) \
|
|
typedef prefix ## _any<HRASCONN,close_hrasconn> prefix ## _hrasconn
|
|
#endif
|
|
|
|
#ifdef __RPCDCE_H__
|
|
# undef DECLARE_SMART_ANY_TYPEDEFS_RPCDCE
|
|
# ifdef UNICODE
|
|
# define DECLARE_SMART_ANY_TYPEDEFS_RPCDCE(prefix) \
|
|
typedef prefix ## _any<RPC_BINDING_HANDLE,close_rpc_binding> prefix ## _rpc_binding; \
|
|
typedef prefix ## _any<RPC_BINDING_VECTOR __RPC_FAR*,close_rpc_vector> prefix ## _rpc_binding_vector; \
|
|
typedef prefix ## _any<unsigned char __RPC_FAR*,close_rpc_string> prefix ## _rpc_string_A; \
|
|
typedef prefix ## _any<unsigned short __RPC_FAR*,close_rpc_string> prefix ## _rpc_string_W; \
|
|
typedef prefix ## _rpc_string_W prefix ## _rpc_string;
|
|
# else
|
|
# define DECLARE_SMART_ANY_TYPEDEFS_RPCDCE(prefix) \
|
|
typedef prefix ## _any<RPC_BINDING_HANDLE,close_rpc_binding> prefix ## _rpc_binding; \
|
|
typedef prefix ## _any<RPC_BINDING_VECTOR __RPC_FAR*,close_rpc_vector> prefix ## _rpc_binding_vector; \
|
|
typedef prefix ## _any<unsigned char __RPC_FAR*,close_rpc_string> prefix ## _rpc_string_A; \
|
|
typedef prefix ## _any<unsigned short __RPC_FAR*,close_rpc_string> prefix ## _rpc_string_W; \
|
|
typedef prefix ## _rpc_string_A prefix ## _rpc_string;
|
|
# endif
|
|
#endif
|
|
|
|
#ifdef _WINSVC_
|
|
# undef DECLARE_SMART_ANY_TYPEDEFS_WINSVC
|
|
# define DECLARE_SMART_ANY_TYPEDEFS_WINSVC(prefix) \
|
|
typedef prefix ## _any<SC_HANDLE,close_service> prefix ## _service; \
|
|
typedef prefix ## _any<SC_LOCK,unlock_service> prefix ## _service_lock;
|
|
#endif
|
|
|
|
#ifdef _WINSOCKAPI_
|
|
# undef DECLARE_SMART_ANY_TYPEDEFS_WINSOCKAPI
|
|
# define DECLARE_SMART_ANY_TYPEDEFS_WINSOCKAPI(prefix) \
|
|
typedef prefix ## _any<SOCKET,close_socket,invalid_socket_t> prefix ## _socket;
|
|
#endif
|
|
|
|
#if defined(_OBJBASE_H_) & !defined(SMART_ANY_CO_INIT)
|
|
# define SMART_ANY_CO_INIT
|
|
inline HRESULT smart_co_init_helper( DWORD dwCoInit )
|
|
{
|
|
(void) dwCoInit;
|
|
# if (_WIN32_WINNT >= 0x0400 ) | defined(_WIN32_DCOM)
|
|
return ::CoInitializeEx(0,dwCoInit);
|
|
# else
|
|
return ::CoInitialize(0);
|
|
# endif
|
|
}
|
|
inline void smart_co_uninit_helper( HRESULT hr )
|
|
{
|
|
if (SUCCEEDED(hr))
|
|
::CoUninitialize();
|
|
}
|
|
typedef close_fun<void(*)(HRESULT),smart_co_uninit_helper> close_co;
|
|
typedef value_const<HRESULT,CO_E_NOTINITIALIZED> co_not_init;
|
|
# undef DECLARE_SMART_ANY_TYPEDEFS_OBJBASE
|
|
# define DECLARE_SMART_ANY_TYPEDEFS_OBJBASE(prefix) \
|
|
typedef prefix ## _any<LPVOID,close_co_task_free> prefix ## _co_task_ptr;
|
|
#endif
|
|
|
|
|
|
#define DECLARE_SMART_ANY_TYPEDEFS(prefix) \
|
|
DECLARE_SMART_ANY_TYPEDEFS_STDIO(prefix) \
|
|
DECLARE_SMART_ANY_TYPEDEFS_WINDOWS(prefix) \
|
|
DECLARE_SMART_ANY_TYPEDEFS_OLEAUTO(prefix) \
|
|
DECLARE_SMART_ANY_TYPEDEFS_MSGQUEUE(prefix) \
|
|
DECLARE_SMART_ANY_TYPEDEFS_WININET(prefix) \
|
|
DECLARE_SMART_ANY_TYPEDEFS_RAS(prefix) \
|
|
DECLARE_SMART_ANY_TYPEDEFS_RPCDCE(prefix) \
|
|
DECLARE_SMART_ANY_TYPEDEFS_WINSVC(prefix) \
|
|
DECLARE_SMART_ANY_TYPEDEFS_WINSOCKAPI(prefix) \
|
|
DECLARE_SMART_ANY_TYPEDEFS_OBJBASE(prefix)
|