/* 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 #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 struct value_const; struct close_release_com; // // TEMPLATE CLASS auto_any // template class auto_any; // return wrapped resource template T get( auto_any const & t ); // return true if the auto_any contains a currently valid resource template bool valid( auto_any const & t ); // return wrapped resource and give up ownership template T release( auto_any & t ); // destroy designated object template void reset( auto_any & t ); // destroy designated object and store new resource template void reset( auto_any & t, U newT ); // swap the contents of two shared_any objects template void swap( auto_any & left, auto_any & 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 //T* address( auto_any & t ); // // TEMPLATE CLASS shared_any // template class shared_any; // return wrapped resource template T get( shared_any const & t ); // return true if the auto_any contains a currently valid resource template bool valid( shared_any const & t ); // destroy designated object template void reset( shared_any & t ); // destroy designated object and store new resource template void reset( shared_any & t, U newT ); // swap the contents of two shared_any objects template void swap( shared_any & left, shared_any & right ); // // TEMPLATE CLASS scoped_any // template class scoped_any; // return wrapped resource template T get( scoped_any const & t ); // return true if the auto_any contains a currently valid resource template bool valid( scoped_any const & t ); // return wrapped resource and give up ownership template T release( scoped_any & t ); // destroy designated object template void reset( scoped_any & t ); // destroy designated object and store new resource template void reset( scoped_any & 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 //T* address( scoped_any & 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 struct fixup_invalid_value { template struct rebind { typedef invalid_value type; }; }; // for compile-time assertions template struct static_assert; template<> struct static_assert { static_assert() {} }; template struct static_init { static T const value; }; template T const static_init::value = T(); template struct null_helper // unmanaged { template struct inner { static T const get() { return static_init::value; } }; }; template<> struct null_helper // managed { template struct inner { static T const get() { return 0; } }; }; template struct select_helper { template struct inner { typedef T type; }; }; template<> struct select_helper { template struct inner { typedef U type; }; }; template struct select { typedef typename select_helper::template inner::type type; }; template< bool > struct holder_helper { template struct inner { typedef T type; }; }; template< typename T > struct remove_ref { typedef T type; }; #ifdef SMART_ANY_PTS template< typename T > struct remove_ref { typedef T type; }; #endif template T* address_of( T & v ) { return reinterpret_cast( &const_cast( reinterpret_cast(v))); } #ifndef _MANAGED template 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 struct is_managed { private: static yes check( managed_convertible ); static no __cdecl check( ... ); static typename remove_ref::type & make(); public: static bool const value = sizeof( yes ) == sizeof( check( make() ) ); }; #ifdef SMART_ANY_PTS template struct is_managed { static bool const value = true; }; template struct is_managed { static bool const value = true; }; template struct is_managed { static bool const value = is_managed::value; }; template struct is_managed { static bool const value = is_managed::value; }; template struct is_managed { static bool const value = is_managed::value; }; #endif #ifndef __cplusplus_cli template<> struct is_managed { static bool const value = true; }; template<> struct is_managed { static bool const value = true; }; template<> struct is_managed { static bool const value = true; }; template<> struct is_managed { static bool const value = true; }; #endif template<> struct holder_helper { template struct inner { typedef gcroot type; }; }; #endif template struct holder { typedef typename holder_helper::value>::template inner::type type; }; template struct is_delete { static bool const value = false; }; template<> struct is_delete { static bool const value = true; }; // dummy type, don't define struct smart_any_cannot_dereference; // For use in implementing unary operator* template 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 { template struct rebind { typedef value_const type; }; }; #else template struct same_type { static const int value = false; }; template struct same_type { static const int value = true; }; // Handle reference types template struct deref { typedef typename deref::type type; }; // Partially specialize for pointer types template struct deref { typedef T& type; // The result of dereferencing a T* }; // Partially specialize for pointer types template struct deref { typedef typename deref::type type; // The result of dereferencing a T* }; // Partially specialize for pointer types template struct deref { typedef typename deref::type type; // The result of dereferencing a T* }; // Partially specialize for pointer types template struct deref { typedef typename deref::type type; // The result of dereferencing a T* }; // Fully specialize for void* template<> struct deref { typedef smart_any_cannot_dereference type; // cannot dereference a void* }; // Fully specialize for void const* template<> struct deref { typedef smart_any_cannot_dereference type; // cannot dereference a void* }; // Fully specialize for void volatile* template<> struct deref { typedef smart_any_cannot_dereference type; // cannot dereference a void* }; // Fully specialize for void const volatile* template<> struct deref { typedef smart_any_cannot_dereference type; // cannot dereference a void* }; #ifdef _MANAGED // Handle reference types template struct deref { typedef typename deref::type type; }; // Partially specialize for pointer types template struct deref { typedef T MGDREFERENCE type; // The result of dereferencing a T MGDHANDLE }; // Partially specialize for pointer types template struct deref { typedef typename deref::type type; // The result of dereferencing a T MGDHANDLE }; // Partially specialize for pointer types template struct deref { typedef typename deref::type type; // The result of dereferencing a T MGDHANDLE }; // Partially specialize for pointer types template struct deref { typedef typename deref::type type; // The result of dereferencing a T MGDHANDLE }; #ifndef __cplusplus_cli // Fully specialize for void* template<> struct deref { typedef smart_any_cannot_dereference type; // cannot dereference a System::Void MGDHANDLE }; // Fully specialize for void const* template<> struct deref { typedef smart_any_cannot_dereference type; // cannot dereference a System::Void MGDHANDLE }; // Fully specialize for void volatile* template<> struct deref { typedef smart_any_cannot_dereference type; // cannot dereference a System::Void MGDHANDLE }; // Fully specialize for void const volatile* template<> struct deref { 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 struct has_unused { private: template struct wrap_t; template static yes check( wrap_t* ); template static no __cdecl check( ... ); public: static bool const value = ( sizeof(check(0)) == sizeof(yes) ); }; template struct is_handle_helper { static bool const value = ( sizeof(T)==sizeof(int) && has_unused::value ); }; #ifdef _MANAGED template struct is_handle_helper { static bool const value = false; }; #endif template<> struct is_handle_helper { static bool const value = false; }; // used to see whether a given type T is a handle type or not. template struct is_handle { private: typedef typename remove_ref::type>::type deref_t; public: static bool const value = ( same_type::value || is_handle_helper::value ); }; #endif template struct safe_types { typedef T pointer_type; typedef typename deref::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 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 struct safe_types { typedef no_addref_release* pointer_type; typedef no_addref_release& reference_type; static pointer_type to_pointer( T* t ) { return static_cast( t ); } static reference_type to_reference( T* t ) { return *static_cast( t ); } }; #endif } // a generic close policy that uses a ptr to a function template struct close_fun { template static void close( T t ) { Pfn( t ); } }; // free an object allocated with new by calling delete struct close_delete { template 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::value> const cannot_delete_a_handle; #endif delete p; } #ifdef _MANAGED template static void close( gcroot const & p ) { delete static_cast( p ); } #endif }; // free an array allocated with new[] by calling delete[] struct close_delete_array { template 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::value> const cannot_delete_a_handle; #endif delete [] p; } //#ifdef _MANAGED // This is broken because of compiler bugs //template //static void close( gcroot const & p ) //{ // delete [] static_cast( p ); //} //#endif }; // for releasing a COM object struct close_release_com { template static void close( T p ) { p->Release(); } }; // for releasing a __gc IDisposable object struct close_dispose { template static void close( T p ) { p->Dispose(); } }; // some generic invalid_value policies struct null_t { template operator T const() const { return detail::null_helper::value>::template inner::get(); } }; template struct value_const { operator T const() const { return value; } }; template struct value_const_ptr { operator T const&() const { return *value_ptr; } }; #ifdef SMART_ANY_PTS template 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(&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 close_handle; typedef close_fun close_find; typedef close_fun close_library; typedef close_fun close_regkey; typedef close_fun close_file_view; typedef close_fun close_hicon; typedef close_fun close_hgdiobj; typedef close_fun close_haccel; typedef close_fun close_hdc; typedef close_fun close_hmenu; typedef close_fun close_hcursor; typedef close_fun close_window; typedef close_fun close_heap_destroy; typedef close_fun close_local_free; typedef close_fun close_hdesk; typedef close_fun close_hhook; typedef close_fun close_hwinsta; typedef close_fun close_event_source; typedef close_fun close_global_free; typedef value_const invalid_handle_t; #endif #ifdef _OLEAUTO_H_ typedef close_fun close_bstr; #endif #ifdef __MSGQUEUE_H__ typedef close_fun close_msg_queue; #endif #if defined(_WININET_) | defined(_DUBINET_) typedef close_fun close_hinternet; #endif #ifdef _RAS_H_ typedef close_fun 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 close_service; typedef close_fun unlock_service; #endif #ifdef _WINSOCKAPI_ typedef int (__stdcall *pfn_closock_t)( SOCKET ); typedef close_fun(&closesocket)> close_socket; typedef value_const invalid_socket_t; #endif #ifdef _OBJBASE_H_ // For use when releasing memory allocated with CoTaskMemAlloc typedef close_fun 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 prefix ## _file_ptr; #endif #ifdef _WINDOWS_ # undef DECLARE_SMART_ANY_TYPEDEFS_WINDOWS # define DECLARE_SMART_ANY_TYPEDEFS_WINDOWS(prefix) \ typedef prefix ## _any prefix ## _hkey; \ typedef prefix ## _any prefix ## _hfind; \ typedef prefix ## _any prefix ## _hfile; \ typedef prefix ## _any prefix ## _communications_device; \ typedef prefix ## _any prefix ## _console_input; \ typedef prefix ## _any prefix ## _console_input_buffer; \ typedef prefix ## _any prefix ## _console_output; \ typedef prefix ## _any prefix ## _mailslot; \ typedef prefix ## _any prefix ## _pipe; \ typedef prefix ## _any prefix ## _handle; \ typedef prefix ## _any prefix ## _access_token; \ typedef prefix ## _any prefix ## _event; \ typedef prefix ## _any prefix ## _file_mapping; \ typedef prefix ## _any prefix ## _job; \ typedef prefix ## _any prefix ## _mutex; \ typedef prefix ## _any prefix ## _process; \ typedef prefix ## _any prefix ## _semaphore; \ typedef prefix ## _any prefix ## _thread; \ typedef prefix ## _any prefix ## _timer; \ typedef prefix ## _any prefix ## _completion_port; \ typedef prefix ## _any prefix ## _hdc; \ typedef prefix ## _any prefix ## _hicon; \ typedef prefix ## _any prefix ## _hmenu; \ typedef prefix ## _any prefix ## _hcursor; \ typedef prefix ## _any prefix ## _hpen; \ typedef prefix ## _any prefix ## _hrgn; \ typedef prefix ## _any prefix ## _hfont; \ typedef prefix ## _any prefix ## _hbrush; \ typedef prefix ## _any prefix ## _hbitmap; \ typedef prefix ## _any prefix ## _hpalette; \ typedef prefix ## _any prefix ## _haccel; \ typedef prefix ## _any prefix ## _window; \ typedef prefix ## _any prefix ## _library; \ typedef prefix ## _any prefix ## _file_view; \ typedef prefix ## _any prefix ## _virtual_ptr; \ typedef prefix ## _any prefix ## _heap; \ typedef prefix ## _any prefix ## _hlocal; \ typedef prefix ## _any prefix ## _hdesk; \ typedef prefix ## _any prefix ## _hhook; \ typedef prefix ## _any prefix ## _hwinsta; \ typedef prefix ## _any prefix ## _event_source; \ typedef prefix ## _any 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 prefix ## _bstr; #endif #ifdef __MSGQUEUE_H__ # undef DECLARE_SMART_ANY_TYPEDEFS_MSGQUEUE # define DECLARE_SMART_ANY_TYPEDEFS_MSGQUEUE(prefix) \ typedef prefix ## _any 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 prefix ## _hinternet; #endif #ifdef _RAS_H_ # undef DECLARE_SMART_ANY_TYPEDEFS_RAS # define DECLARE_SMART_ANY_TYPEDEFS_RAS(prefix) \ typedef prefix ## _any prefix ## _hrasconn #endif #ifdef __RPCDCE_H__ # undef DECLARE_SMART_ANY_TYPEDEFS_RPCDCE # ifdef UNICODE # define DECLARE_SMART_ANY_TYPEDEFS_RPCDCE(prefix) \ typedef prefix ## _any prefix ## _rpc_binding; \ typedef prefix ## _any prefix ## _rpc_binding_vector; \ typedef prefix ## _any prefix ## _rpc_string_A; \ typedef prefix ## _any prefix ## _rpc_string_W; \ typedef prefix ## _rpc_string_W prefix ## _rpc_string; # else # define DECLARE_SMART_ANY_TYPEDEFS_RPCDCE(prefix) \ typedef prefix ## _any prefix ## _rpc_binding; \ typedef prefix ## _any prefix ## _rpc_binding_vector; \ typedef prefix ## _any prefix ## _rpc_string_A; \ typedef prefix ## _any 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 prefix ## _service; \ typedef prefix ## _any prefix ## _service_lock; #endif #ifdef _WINSOCKAPI_ # undef DECLARE_SMART_ANY_TYPEDEFS_WINSOCKAPI # define DECLARE_SMART_ANY_TYPEDEFS_WINSOCKAPI(prefix) \ typedef prefix ## _any 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 close_co; typedef value_const co_not_init; # undef DECLARE_SMART_ANY_TYPEDEFS_OBJBASE # define DECLARE_SMART_ANY_TYPEDEFS_OBJBASE(prefix) \ typedef prefix ## _any 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)