Dryad/xcompute_native/inc/scoped_any.h

274 lines
8.7 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: scoped_any.h
//
// Contents: automatic resource management, a-la std::scoped_ptr
//
// Classes: scoped_any<> and various typedefs
//
// Functions: get
// reset
// release
// valid
// address
//
//----------------------------------------------------------------------------
#ifndef SCOPED_ANY
#define SCOPED_ANY
#include <cassert>
#include "smart_any_fwd.h"
#pragma warning(push)
// 4284 warning for operator-> returning non-pointer;
// compiler issues it even if -> is not used for the specific instance
#pragma warning(disable: 4284)
namespace detail
{
// friend function definitions go in scoped_any_helper
template<typename T,class close_policy,class invalid_value,int unique>
struct scoped_any_helper;
}
// wrap a resource to enforce strict ownership and ensure proper cleanup
template<typename T,class close_policy,class invalid_value,int unique>
class scoped_any
{
// disallow copy and assignment
scoped_any( scoped_any<T,close_policy,invalid_value,unique> const & );
scoped_any<T,close_policy,invalid_value,unique> & operator=(
scoped_any<T,close_policy,invalid_value,unique> const & );
// disallow comparison of scoped_any's
bool operator==( detail::safe_bool ) const;
bool operator!=( detail::safe_bool ) const;
typedef detail::safe_types<T,close_policy> safe_types;
public:
typedef typename detail::holder<T>::type element_type;
typedef close_policy close_policy_type;
typedef typename safe_types::pointer_type pointer_type;
typedef typename safe_types::reference_type reference_type;
// Fix-up the invalid_value type on older compilers
typedef typename detail::fixup_invalid_value<invalid_value>::
template rebind<T>::type invalid_value_type;
friend struct detail::scoped_any_helper<T,close_policy,invalid_value,unique>;
// construct from object pointer
explicit scoped_any( T t = invalid_value_type() )
: m_t( t )
{
}
// destroy the object
~scoped_any()
{
if( valid() )
{
close_policy::close( m_t );
}
}
// return pointer to class object (assume pointer)
pointer_type operator->() const
{
#ifdef SMART_ANY_PTS
// You better not be applying operator-> to a handle!
static detail::static_assert<!detail::is_handle<T>::value> const cannot_dereference_a_handle;
#endif
assert( valid() );
return safe_types::to_pointer( m_t );
}
// for use when scoped_any appears in a conditional
operator detail::safe_bool() const
{
return valid() ? detail::safe_true : detail::safe_false;
}
// for use when scoped_any appears in a conditional
bool operator!() const
{
return ! valid();
}
#ifdef SMART_ANY_PTS
// if this scoped_any is managing an array, we can use operator[] to index it
typename detail::deref<T>::type operator[]( int i ) const
{
static detail::static_assert<!detail::is_handle<T>::value> const cannot_dereference_a_handle;
static detail::static_assert<!detail::is_delete<close_policy>::value> const accessed_like_an_array_but_not_deleted_like_an_array;
assert( valid() );
return m_t[ i ];
}
// unary operator* lets you write code like:
// scoped_any<foo*,close_delete> pfoo( new foo );
// foo & f = *pfoo;
reference_type operator*() const
{
static detail::static_assert<!detail::is_handle<T>::value> const cannot_dereference_a_handle;
assert( valid() );
return safe_types::to_reference( m_t );
}
#endif
private:
bool valid() const
{
// see if the managed resource is in the invalid state.
return m_t != static_cast<T>( invalid_value_type() );
}
// the wrapped object
element_type m_t;
};
namespace detail
{
// friend function definitions go in scoped_any_helper
template<typename T,class close_policy,class invalid_value,int unique>
struct scoped_any_helper
{
// return wrapped pointer
static T get( scoped_any<T,close_policy,invalid_value,unique> const & t )
{
return t.m_t;
}
// return wrapped pointer and give up ownership
static T release( scoped_any<T,close_policy,invalid_value,unique> & t )
{
// Fix-up the invalid_value type on older compilers
typedef typename detail::fixup_invalid_value<invalid_value>::
template rebind<T>::type invalid_value_type;
T tmpT = t.m_t;
t.m_t = static_cast<T>( invalid_value_type() );
return tmpT;
}
// destroy designated object and store new pointer
static void reset( scoped_any<T,close_policy,invalid_value,unique> & t, T newT )
{
if( t.m_t != newT )
{
if( t.valid() )
{
close_policy::close( t.m_t );
}
t.m_t = newT;
}
}
typedef typename scoped_any<T,close_policy,invalid_value,unique>::element_type element_type;
// return the address of the wrapped pointer
static element_type* address( scoped_any<T,close_policy,invalid_value,unique> & t )
{
// check to make sure the wrapped object is in the invalid state
assert( !t.valid() );
return address_of( t.m_t );
}
};
}
// return wrapped resource
template<typename T,class close_policy,class invalid_value,int unique>
inline T get( scoped_any<T,close_policy,invalid_value,unique> const & t )
{
return detail::scoped_any_helper<T,close_policy,invalid_value,unique>::get( t );
}
// return true if the scoped_any contains a currently valid resource
template<typename T,class close_policy,class invalid_value,int unique>
inline bool valid( scoped_any<T,close_policy,invalid_value,unique> const & t )
{
return t;
}
// return wrapped resource and give up ownership
template<typename T,class close_policy,class invalid_value,int unique>
inline T release( scoped_any<T,close_policy,invalid_value,unique> & t )
{
return detail::scoped_any_helper<T,close_policy,invalid_value,unique>::release( t );
}
// destroy designated object and store new resource
template<typename T,class close_policy,class invalid_value,int unique>
inline void reset( scoped_any<T,close_policy,invalid_value,unique> & t )
{
typedef typename detail::fixup_invalid_value<invalid_value>::
template rebind<T>::type invalid_value_type;
detail::scoped_any_helper<T,close_policy,invalid_value,unique>::reset( t, invalid_value_type() );
}
// destroy designated object and store new resource
template<typename T,class close_policy,class invalid_value,int unique,typename U>
inline void reset( scoped_any<T,close_policy,invalid_value,unique> & t, U newT )
{
detail::scoped_any_helper<T,close_policy,invalid_value,unique>::reset( t, 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>
inline typename scoped_any<T,close_policy,invalid_value,unique>::element_type*
address( scoped_any<T,close_policy,invalid_value,unique> & t )
{
return detail::scoped_any_helper<T,close_policy,invalid_value,unique>::address( t );
}
#pragma warning(pop)
#endif
// This causes the scoped_* typedefs to be defined
DECLARE_SMART_ANY_TYPEDEFS(scoped)
#if defined(_OBJBASE_H_) & !defined(SCOPED_ANY_CO_INIT)
# define SCOPED_ANY_CO_INIT
typedef scoped_any<HRESULT,close_co,co_not_init> scoped_co_close;
// Helper class for balancing calls to CoInitialize and CoUninitialize
struct scoped_co_init
{
explicit scoped_co_init( DWORD dwCoInit = COINIT_APARTMENTTHREADED )
: m_hr( smart_co_init_helper( dwCoInit ) )
{
}
HRESULT hresult() const
{
return get(m_hr);
}
scoped_co_close const m_hr;
};
#endif