fix line endings
git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@896 7ec92016-0320-0410-acc4-a06ded1c099a
This commit is contained in:
parent
0c4789ee11
commit
683474eff9
18 changed files with 5859 additions and 5859 deletions
|
@ -1,153 +1,153 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The Loki Library
|
||||
// Copyright (c) 2008 by Rich Sposato
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software for any
|
||||
// purpose is hereby granted without fee, provided that the above copyright
|
||||
// notice appear in all copies and that both that copyright notice and this
|
||||
// permission notice appear in supporting documentation.
|
||||
// The author makes no representations about the
|
||||
// suitability of this software for any purpose. It is provided "as is"
|
||||
// without express or implied warranty.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef LOKI_ALLOCATOR_HPP_INCLUDED
|
||||
#define LOKI_ALLOCATOR_HPP_INCLUDED
|
||||
|
||||
// $Id$
|
||||
|
||||
// Requires project to be compiled with loki/src/SmallObj.cpp and loki/src/Singleton.cpp
|
||||
|
||||
#include <loki/SmallObj.h>
|
||||
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** @class LokiAllocator
|
||||
Adapts Loki's Small-Object Allocator for STL container classes.
|
||||
This class provides all the functionality required for STL allocators, but
|
||||
uses Loki's Small-Object Allocator to perform actual memory operations.
|
||||
Implementation comes from a post in Loki forums (by Rasmus Ekman?).
|
||||
*/
|
||||
template
|
||||
<
|
||||
typename Type,
|
||||
typename AllocT = Loki::AllocatorSingleton<>
|
||||
>
|
||||
class LokiAllocator
|
||||
{
|
||||
public:
|
||||
|
||||
typedef ::std::size_t size_type;
|
||||
typedef ::std::ptrdiff_t difference_type;
|
||||
typedef Type * pointer;
|
||||
typedef const Type * const_pointer;
|
||||
typedef Type & reference;
|
||||
typedef const Type & const_reference;
|
||||
typedef Type value_type;
|
||||
|
||||
/// Default constructor does nothing.
|
||||
inline LokiAllocator( void ) throw() { }
|
||||
|
||||
/// Copy constructor does nothing.
|
||||
inline LokiAllocator( const LokiAllocator & ) throw() { }
|
||||
|
||||
/// Type converting allocator constructor does nothing.
|
||||
template < typename Type1 >
|
||||
inline LokiAllocator( const LokiAllocator< Type1 > & ) throw() { }
|
||||
|
||||
/// Destructor does nothing.
|
||||
inline ~LokiAllocator() throw() { }
|
||||
|
||||
/// Convert an allocator<Type> to an allocator <Type1>.
|
||||
template < typename Type1 >
|
||||
struct rebind
|
||||
{
|
||||
typedef LokiAllocator< Type1 > other;
|
||||
};
|
||||
|
||||
/// Return address of reference to mutable element.
|
||||
pointer address( reference elem ) const { return &elem; }
|
||||
|
||||
/// Return address of reference to const element.
|
||||
const_pointer address( const_reference elem ) const { return &elem; }
|
||||
|
||||
/** Allocate an array of count elements. Warning! The true parameter in
|
||||
the call to Allocate means this function can throw exceptions. This is
|
||||
better than not throwing, and returning a null pointer in case the caller
|
||||
assumes the return value is not null.
|
||||
@param count # of elements in array.
|
||||
@param hint Place where caller thinks allocation should occur.
|
||||
@return Pointer to block of memory.
|
||||
*/
|
||||
pointer allocate( size_type count, const void * hint = 0 )
|
||||
{
|
||||
(void)hint; // Ignore the hint.
|
||||
void * p = AllocT::Instance().Allocate( count * sizeof( Type ), true );
|
||||
return reinterpret_cast< pointer >( p );
|
||||
}
|
||||
|
||||
/// Ask allocator to release memory at pointer with size bytes.
|
||||
void deallocate( pointer p, size_type size )
|
||||
{
|
||||
AllocT::Instance().Deallocate( p, size * sizeof( Type ) );
|
||||
}
|
||||
|
||||
/// Calculate max # of elements allocator can handle.
|
||||
size_type max_size( void ) const throw()
|
||||
{
|
||||
// A good optimizer will see these calculations always produce the same
|
||||
// value and optimize this function away completely.
|
||||
const size_type max_bytes = size_type( -1 );
|
||||
const size_type bytes = max_bytes / sizeof( Type );
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/// Construct an element at the pointer.
|
||||
void construct( pointer p, const Type & value )
|
||||
{
|
||||
// A call to global placement new forces a call to copy constructor.
|
||||
::new( p ) Type( value );
|
||||
}
|
||||
|
||||
/// Destruct the object at pointer.
|
||||
void destroy( pointer p )
|
||||
{
|
||||
// If the Type has no destructor, then some compilers complain about
|
||||
// an unreferenced parameter, so use the void cast trick to prevent
|
||||
// spurious warnings.
|
||||
(void)p;
|
||||
p->~Type();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** All equality operators return true since LokiAllocator is basically a
|
||||
monostate design pattern, so all instances of it are identical.
|
||||
*/
|
||||
template < typename Type >
|
||||
inline bool operator == ( const LokiAllocator< Type > &, const LokiAllocator< Type > & )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/** All inequality operators return false since LokiAllocator is basically a
|
||||
monostate design pattern, so all instances of it are identical.
|
||||
*/
|
||||
template < typename Type >
|
||||
inline bool operator != ( const LokiAllocator< Type > & , const LokiAllocator< Type > & )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
} // namespace Loki
|
||||
|
||||
#endif // LOKI_ALLOCATOR_INCLUDED
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The Loki Library
|
||||
// Copyright (c) 2008 by Rich Sposato
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software for any
|
||||
// purpose is hereby granted without fee, provided that the above copyright
|
||||
// notice appear in all copies and that both that copyright notice and this
|
||||
// permission notice appear in supporting documentation.
|
||||
// The author makes no representations about the
|
||||
// suitability of this software for any purpose. It is provided "as is"
|
||||
// without express or implied warranty.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef LOKI_ALLOCATOR_HPP_INCLUDED
|
||||
#define LOKI_ALLOCATOR_HPP_INCLUDED
|
||||
|
||||
// $Id$
|
||||
|
||||
// Requires project to be compiled with loki/src/SmallObj.cpp and loki/src/Singleton.cpp
|
||||
|
||||
#include <loki/SmallObj.h>
|
||||
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** @class LokiAllocator
|
||||
Adapts Loki's Small-Object Allocator for STL container classes.
|
||||
This class provides all the functionality required for STL allocators, but
|
||||
uses Loki's Small-Object Allocator to perform actual memory operations.
|
||||
Implementation comes from a post in Loki forums (by Rasmus Ekman?).
|
||||
*/
|
||||
template
|
||||
<
|
||||
typename Type,
|
||||
typename AllocT = Loki::AllocatorSingleton<>
|
||||
>
|
||||
class LokiAllocator
|
||||
{
|
||||
public:
|
||||
|
||||
typedef ::std::size_t size_type;
|
||||
typedef ::std::ptrdiff_t difference_type;
|
||||
typedef Type * pointer;
|
||||
typedef const Type * const_pointer;
|
||||
typedef Type & reference;
|
||||
typedef const Type & const_reference;
|
||||
typedef Type value_type;
|
||||
|
||||
/// Default constructor does nothing.
|
||||
inline LokiAllocator( void ) throw() { }
|
||||
|
||||
/// Copy constructor does nothing.
|
||||
inline LokiAllocator( const LokiAllocator & ) throw() { }
|
||||
|
||||
/// Type converting allocator constructor does nothing.
|
||||
template < typename Type1 >
|
||||
inline LokiAllocator( const LokiAllocator< Type1 > & ) throw() { }
|
||||
|
||||
/// Destructor does nothing.
|
||||
inline ~LokiAllocator() throw() { }
|
||||
|
||||
/// Convert an allocator<Type> to an allocator <Type1>.
|
||||
template < typename Type1 >
|
||||
struct rebind
|
||||
{
|
||||
typedef LokiAllocator< Type1 > other;
|
||||
};
|
||||
|
||||
/// Return address of reference to mutable element.
|
||||
pointer address( reference elem ) const { return &elem; }
|
||||
|
||||
/// Return address of reference to const element.
|
||||
const_pointer address( const_reference elem ) const { return &elem; }
|
||||
|
||||
/** Allocate an array of count elements. Warning! The true parameter in
|
||||
the call to Allocate means this function can throw exceptions. This is
|
||||
better than not throwing, and returning a null pointer in case the caller
|
||||
assumes the return value is not null.
|
||||
@param count # of elements in array.
|
||||
@param hint Place where caller thinks allocation should occur.
|
||||
@return Pointer to block of memory.
|
||||
*/
|
||||
pointer allocate( size_type count, const void * hint = 0 )
|
||||
{
|
||||
(void)hint; // Ignore the hint.
|
||||
void * p = AllocT::Instance().Allocate( count * sizeof( Type ), true );
|
||||
return reinterpret_cast< pointer >( p );
|
||||
}
|
||||
|
||||
/// Ask allocator to release memory at pointer with size bytes.
|
||||
void deallocate( pointer p, size_type size )
|
||||
{
|
||||
AllocT::Instance().Deallocate( p, size * sizeof( Type ) );
|
||||
}
|
||||
|
||||
/// Calculate max # of elements allocator can handle.
|
||||
size_type max_size( void ) const throw()
|
||||
{
|
||||
// A good optimizer will see these calculations always produce the same
|
||||
// value and optimize this function away completely.
|
||||
const size_type max_bytes = size_type( -1 );
|
||||
const size_type bytes = max_bytes / sizeof( Type );
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/// Construct an element at the pointer.
|
||||
void construct( pointer p, const Type & value )
|
||||
{
|
||||
// A call to global placement new forces a call to copy constructor.
|
||||
::new( p ) Type( value );
|
||||
}
|
||||
|
||||
/// Destruct the object at pointer.
|
||||
void destroy( pointer p )
|
||||
{
|
||||
// If the Type has no destructor, then some compilers complain about
|
||||
// an unreferenced parameter, so use the void cast trick to prevent
|
||||
// spurious warnings.
|
||||
(void)p;
|
||||
p->~Type();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** All equality operators return true since LokiAllocator is basically a
|
||||
monostate design pattern, so all instances of it are identical.
|
||||
*/
|
||||
template < typename Type >
|
||||
inline bool operator == ( const LokiAllocator< Type > &, const LokiAllocator< Type > & )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/** All inequality operators return false since LokiAllocator is basically a
|
||||
monostate design pattern, so all instances of it are identical.
|
||||
*/
|
||||
template < typename Type >
|
||||
inline bool operator != ( const LokiAllocator< Type > & , const LokiAllocator< Type > & )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
} // namespace Loki
|
||||
|
||||
#endif // LOKI_ALLOCATOR_INCLUDED
|
||||
|
|
|
@ -1,96 +1,96 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The Loki Library
|
||||
// Copyright (c) 2007 by Rich Sposato
|
||||
// Permission to use, copy, modify, distribute and sell this software for any
|
||||
// purpose is hereby granted without fee, provided that the above copyright
|
||||
// notice appear in all copies and that both that copyright notice and this
|
||||
// permission notice appear in supporting documentation.
|
||||
// The author makes no representations about the
|
||||
// suitability of this software for any purpose. It is provided "as is"
|
||||
// without express or implied warranty.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef LOKI_CHECK_RETURN_INC_
|
||||
#define LOKI_CHECK_RETURN_INC_
|
||||
|
||||
// $Id$
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \class CheckReturn
|
||||
///
|
||||
/// \par Purpose
|
||||
/// C++ provides no mechanism within the language itself to force code to
|
||||
/// check the return value from a function call. This simple class provides
|
||||
/// a mechanism by which programmers can force calling functions to check the
|
||||
/// return value. Or at least make them consciously choose to disregard the
|
||||
/// return value. If the calling function fails to use or store the return
|
||||
/// value, the destructor asserts.
|
||||
///
|
||||
/// \par Return Type
|
||||
/// The returned value is copied into CheckReturn rather than accessed via a
|
||||
/// a reference or pointer since return value could be local to a function.
|
||||
/// CheckReturn works best when the return type is a built-in primitive (bool,
|
||||
/// int, etc...) a pointer, or an enum (such as an error condition enum). It
|
||||
/// can work with other types that have cheap copy operations.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template < class Value >
|
||||
class CheckReturn
|
||||
{
|
||||
public:
|
||||
|
||||
/// Conversion constructor changes Value type to CheckReturn type.
|
||||
inline CheckReturn( Value value ) :
|
||||
m_value( value ), m_checked( false ) {}
|
||||
|
||||
/// Copy-constructor allows functions to call another function within the
|
||||
/// return statement. The other CheckReturn's m_checked flag is set since
|
||||
/// its duty has been passed to the m_checked flag in this one.
|
||||
inline CheckReturn( const CheckReturn & that ) :
|
||||
m_value( that.m_value ), m_checked( false )
|
||||
{ that.m_checked = true; }
|
||||
|
||||
/// Destructor checks if return value was used.
|
||||
inline ~CheckReturn( void )
|
||||
{
|
||||
// If this assertion fails, then a function failed to check the
|
||||
// return value from a function call.
|
||||
assert( m_checked );
|
||||
}
|
||||
|
||||
/// Conversion operator changes CheckReturn back to Value type.
|
||||
inline operator Value ( void )
|
||||
{
|
||||
m_checked = true;
|
||||
return m_value;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Default constructor not implemented.
|
||||
CheckReturn( void );
|
||||
|
||||
/// Copy-assignment operator not implemented.
|
||||
CheckReturn & operator = ( const CheckReturn & that );
|
||||
|
||||
/// Copy of returned value.
|
||||
Value m_value;
|
||||
|
||||
/// Flag for whether calling function checked return value yet.
|
||||
mutable bool m_checked;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
} // namespace Loki
|
||||
|
||||
#endif // end file guardian
|
||||
|
||||
// $Log$
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The Loki Library
|
||||
// Copyright (c) 2007 by Rich Sposato
|
||||
// Permission to use, copy, modify, distribute and sell this software for any
|
||||
// purpose is hereby granted without fee, provided that the above copyright
|
||||
// notice appear in all copies and that both that copyright notice and this
|
||||
// permission notice appear in supporting documentation.
|
||||
// The author makes no representations about the
|
||||
// suitability of this software for any purpose. It is provided "as is"
|
||||
// without express or implied warranty.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef LOKI_CHECK_RETURN_INC_
|
||||
#define LOKI_CHECK_RETURN_INC_
|
||||
|
||||
// $Id$
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \class CheckReturn
|
||||
///
|
||||
/// \par Purpose
|
||||
/// C++ provides no mechanism within the language itself to force code to
|
||||
/// check the return value from a function call. This simple class provides
|
||||
/// a mechanism by which programmers can force calling functions to check the
|
||||
/// return value. Or at least make them consciously choose to disregard the
|
||||
/// return value. If the calling function fails to use or store the return
|
||||
/// value, the destructor asserts.
|
||||
///
|
||||
/// \par Return Type
|
||||
/// The returned value is copied into CheckReturn rather than accessed via a
|
||||
/// a reference or pointer since return value could be local to a function.
|
||||
/// CheckReturn works best when the return type is a built-in primitive (bool,
|
||||
/// int, etc...) a pointer, or an enum (such as an error condition enum). It
|
||||
/// can work with other types that have cheap copy operations.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template < class Value >
|
||||
class CheckReturn
|
||||
{
|
||||
public:
|
||||
|
||||
/// Conversion constructor changes Value type to CheckReturn type.
|
||||
inline CheckReturn( Value value ) :
|
||||
m_value( value ), m_checked( false ) {}
|
||||
|
||||
/// Copy-constructor allows functions to call another function within the
|
||||
/// return statement. The other CheckReturn's m_checked flag is set since
|
||||
/// its duty has been passed to the m_checked flag in this one.
|
||||
inline CheckReturn( const CheckReturn & that ) :
|
||||
m_value( that.m_value ), m_checked( false )
|
||||
{ that.m_checked = true; }
|
||||
|
||||
/// Destructor checks if return value was used.
|
||||
inline ~CheckReturn( void )
|
||||
{
|
||||
// If this assertion fails, then a function failed to check the
|
||||
// return value from a function call.
|
||||
assert( m_checked );
|
||||
}
|
||||
|
||||
/// Conversion operator changes CheckReturn back to Value type.
|
||||
inline operator Value ( void )
|
||||
{
|
||||
m_checked = true;
|
||||
return m_value;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Default constructor not implemented.
|
||||
CheckReturn( void );
|
||||
|
||||
/// Copy-assignment operator not implemented.
|
||||
CheckReturn & operator = ( const CheckReturn & that );
|
||||
|
||||
/// Copy of returned value.
|
||||
Value m_value;
|
||||
|
||||
/// Flag for whether calling function checked return value yet.
|
||||
mutable bool m_checked;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
} // namespace Loki
|
||||
|
||||
#endif // end file guardian
|
||||
|
||||
// $Log$
|
||||
|
|
|
@ -1,453 +1,453 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// The Loki Library
|
||||
// Copyright (c) 2008 Rich Sposato
|
||||
// The copyright on this file is protected under the terms of the MIT license.
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software for any
|
||||
// purpose is hereby granted without fee, provided that the above copyright
|
||||
// notice appear in all copies and that both that copyright notice and this
|
||||
// permission notice appear in supporting documentation.
|
||||
//
|
||||
// The author makes no representations about the suitability of this software
|
||||
// for any purpose. It is provided "as is" without express or implied warranty.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// $Id$
|
||||
|
||||
/// @file Checker.h This file provides Loki's Checker facility.
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#ifndef LOKI_CHECKER_H_INCLUDED
|
||||
#define LOKI_CHECKER_H_INCLUDED
|
||||
|
||||
#include <exception> // needed for calls to uncaught_exception.
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
|
||||
/** @par Checker and StaticChecker Overview
|
||||
The Checker and StaticChecker classes have two purposes:
|
||||
- provide a mechanism by which programmers can determine which functions
|
||||
violate class/data invariants,
|
||||
- and determine which exception safety a function provides.
|
||||
|
||||
@par Class & Data Invariants
|
||||
The Checker and StaticChecker utilities define invariants as "expressions that
|
||||
are true for particular data". They uses a function which returns true if all
|
||||
data are valid, and returns false if any datum is invalid. This is called the
|
||||
validator function, and the host class or function provides a pointer to it.
|
||||
The validator could also assert for any invariant which fails rather than
|
||||
return false. If the validator is a static member function, you can use it
|
||||
with checkers in any function, but especially standalone functions and class
|
||||
static functions. If the validator is a non-static member function, you can
|
||||
use it only within non-static member functions.
|
||||
|
||||
@par Exception Safety Levels
|
||||
Years ago, David Abrahams formalized a framework for assessing the exception
|
||||
safety level a function provides. His framework describes three levels of
|
||||
guarantees. Any function which does not provide any of these levels is
|
||||
considered unsafe. Checker and StaticChecker determine a function's safety
|
||||
level through the use of policy classes. Checker's policy classes can show if
|
||||
a function provides any of these three guarantees. (Caveat: Checker can't
|
||||
detect leaks directly by itself, but it can call a validator which does.)
|
||||
StaticChecker's policy classes only provide direct checking for the no-throw
|
||||
and invariant guarantees. With some finesse, a programmer can write a
|
||||
validator for StaticChecker that checks for the Strong guarantee.
|
||||
|
||||
- No-throw guarantee: A function will not throw any exceptions.
|
||||
- Strong guarantee: A function will not change data if an exception occurs.
|
||||
(Also called the no-change guarantee.)
|
||||
- Basic guarantee: A function will not leak resources and data will remain
|
||||
in a valid state if an exception occurs. (Also called a no-leak guarantee.)
|
||||
*/
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/** @class CheckForNoThrow
|
||||
|
||||
@par Exception Safety Level:
|
||||
This exception-checking policy class for Checker asserts if an exception exists.
|
||||
Host classes can use this to show that some member functions provide the no-throw
|
||||
exception safety guarantees.
|
||||
|
||||
@par Requirements For Host Class:
|
||||
This policy imposes no requirements on a host class.
|
||||
*/
|
||||
template < class Host >
|
||||
class CheckForNoThrow
|
||||
{
|
||||
public:
|
||||
|
||||
inline explicit CheckForNoThrow( const Host * ) {}
|
||||
|
||||
inline void Check( const Host * ) const
|
||||
{
|
||||
assert( !::std::uncaught_exception() );
|
||||
}
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/** @class CheckForNoChange
|
||||
|
||||
@par Exception Safety Level:
|
||||
This exception-checking policy class for Checker asserts only if a copy of the
|
||||
host differs from the host object when an exception occurs. Host classes can
|
||||
use this policy to show which member functions provide the strong exception
|
||||
guarantee.
|
||||
|
||||
@par Requirements:
|
||||
This policy requires hosts to provide both the copy-constructor and the
|
||||
equality operator, and is intended for classes with value semantics.
|
||||
equality operator.
|
||||
*/
|
||||
|
||||
template < class Host >
|
||||
class CheckForNoChange
|
||||
{
|
||||
public:
|
||||
|
||||
inline explicit CheckForNoChange( const Host * host ) :
|
||||
m_compare( *host ) {}
|
||||
|
||||
inline void Check( const Host * host ) const
|
||||
{
|
||||
if ( ::std::uncaught_exception() )
|
||||
{
|
||||
assert( m_compare == *host );
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Host m_compare;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/** @class CheckForNoChangeOrThrow
|
||||
|
||||
@par Exception Safety Level:
|
||||
This exception-checking policy class for Checker asserts either if a copy of
|
||||
the host differs from the original host object, or if an exception occurs.
|
||||
Host classes can use this policy to show which member functions provide the
|
||||
no-throw exception guarantee, and would never change data anyway.
|
||||
|
||||
@par Requirements For Host Class:
|
||||
This policy requires hosts to provide both the copy-constructor and the
|
||||
equality operator, and is intended for classes with value semantics.
|
||||
*/
|
||||
|
||||
template < class Host >
|
||||
class CheckForNoChangeOrThrow
|
||||
{
|
||||
public:
|
||||
|
||||
inline explicit CheckForNoChangeOrThrow( const Host * host ) :
|
||||
m_compare( *host ) {}
|
||||
|
||||
inline void Check( const Host * host ) const
|
||||
{
|
||||
assert( !::std::uncaught_exception() );
|
||||
assert( m_compare == *host );
|
||||
}
|
||||
|
||||
private:
|
||||
Host m_compare;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/** @class CheckForEquality
|
||||
|
||||
@par Exception Safety Level:
|
||||
This exception-checking policy class for Checker asserts only if a copy of the
|
||||
host differs from the host object regardless of whether an exception occurs.
|
||||
Host classes can use this policy to show which member functions never change
|
||||
data members, and thereby provide the strong exception safety level by default.
|
||||
|
||||
@par Requirements For Host Class:
|
||||
This policy requires hosts to provide both the copy-constructor and the
|
||||
equality operator, and is intended for classes with value semantics.
|
||||
*/
|
||||
|
||||
template < class Host >
|
||||
class CheckForEquality
|
||||
{
|
||||
public:
|
||||
|
||||
inline explicit CheckForEquality( const Host * host ) :
|
||||
m_compare( *host ) {}
|
||||
|
||||
inline void Check( const Host * host ) const
|
||||
{
|
||||
assert( m_compare == *host );
|
||||
}
|
||||
|
||||
private:
|
||||
Host m_compare;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/** @class CheckForNothing
|
||||
|
||||
@par Exception Safety Level:
|
||||
This exception-checking policy class for Checker does nothing when called.
|
||||
Host classes can use this to show which member functions provide neither the
|
||||
strong nor no-throw exception guarantees. The best guarantee such functions
|
||||
can provide is that nothing gets leaked.
|
||||
|
||||
@par Requirements For Host Class:
|
||||
This policy imposes no requirements on a host class.
|
||||
*/
|
||||
|
||||
template < class Host >
|
||||
class CheckForNothing
|
||||
{
|
||||
public:
|
||||
inline explicit CheckForNothing( const Host * ) {}
|
||||
inline void Check( const Host * ) const {}
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/** @class Checker
|
||||
This class checks if a host class violated an invariant. This asserts if any
|
||||
check for an invariant failed. It can also demonstrate which functions provide
|
||||
which exception safety level.
|
||||
|
||||
@par Usage
|
||||
-# Implement a function that checks each class invariant. The function must
|
||||
have the signature similar to the Validator type. Something like:
|
||||
"bool Host::IsValid( void ) const;"
|
||||
- The function should return true if everything is okay, but false if
|
||||
something is wrong.
|
||||
- Or it could assert if anything is wrong.
|
||||
-# Declare some typedef's inside the class declaration like these. Make one
|
||||
typedef for each exception policy you use. I typedef'ed the CheckForNothing
|
||||
policy as CheckInvariants because even if a function can't provide either the
|
||||
no-throw nor the no-change policies, it should still make sure the object
|
||||
remains in a valid state.
|
||||
- typedef ::Loki::Checker< Host, ::Loki::CheckForNoThrow > CheckForNoThrow;
|
||||
- typedef ::Loki::Checker< Host, ::Loki::CheckForNoChange > CheckForNoChange;
|
||||
- typedef ::Loki::Checker< Host, ::Loki::CheckForEquality > CheckForEquality;
|
||||
- typedef ::Loki::Checker< Host, ::Loki::CheckForNothing > CheckInvariants;
|
||||
-# Construct a checker near the top of each member function - except in the
|
||||
validator member function. Pass the this pointer and the address of your
|
||||
validator function into the checker's constructor.
|
||||
- If the function never throws, then use the CheckForNoThrow policy.
|
||||
- If the function never changes any data members, then use CheckForEquality
|
||||
policy.
|
||||
- If the function's normal execution flow changes data, but must make sure
|
||||
data remains unchanged when any exceptions occur, then use the
|
||||
CheckForNoChange policy.
|
||||
- Otherwise use the CheckInvariants policy.
|
||||
-# Recompile a debug version of your program, run it, and look for which
|
||||
assertions failed.
|
||||
*/
|
||||
|
||||
template
|
||||
<
|
||||
class Host,
|
||||
template < class > class ExceptionPolicy
|
||||
>
|
||||
class Checker : public ExceptionPolicy< Host >
|
||||
{
|
||||
/// Shorthand for the ExceptionPolicy class.
|
||||
typedef ExceptionPolicy< Host > Ep;
|
||||
|
||||
public:
|
||||
|
||||
/// Signature for the validation function.
|
||||
typedef bool ( Host:: * Validator )( void ) const;
|
||||
|
||||
/** The constructor makes sure the host is valid at the time the checker
|
||||
was created, thus insuring the host object was not corrupt from the start.
|
||||
*/
|
||||
inline Checker( const Host * host, Validator validator ) :
|
||||
Ep( host ),
|
||||
m_host( host ),
|
||||
m_validator( validator )
|
||||
{
|
||||
Check();
|
||||
}
|
||||
|
||||
/** The destructor checks if any Host invariants failed, and then calls the
|
||||
ExceptionPolicy's Check function to determine what to do in case of an
|
||||
exception.
|
||||
*/
|
||||
inline ~Checker( void )
|
||||
{
|
||||
Check();
|
||||
Ep::Check( m_host );
|
||||
}
|
||||
|
||||
/** This first checks the invariants for Checker, and then calls the
|
||||
validator function for the host to make sure no class invariants
|
||||
were broken by the host within the Host's member function body. The
|
||||
host member function can call Check directly to verify the object
|
||||
remains valid at any time.
|
||||
*/
|
||||
inline void Check( void ) const
|
||||
{
|
||||
assert( 0 != this );
|
||||
assert( 0 != m_host );
|
||||
assert( 0 != m_validator );
|
||||
// Now that this confirms the pointers to the host and validation
|
||||
// functions are not null, go ahead and validate the host object.
|
||||
assert( ( m_host->*( m_validator ) )() );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/// Default constructor is not implemented.
|
||||
Checker( void );
|
||||
/// Copy constructor is not implemented.
|
||||
Checker( const Checker & );
|
||||
/// Copy-assignment operator is not implemented.
|
||||
Checker & operator = ( const Checker & );
|
||||
|
||||
/// Pointer to the host object.
|
||||
const Host * m_host;
|
||||
|
||||
/// Pointer to member function that checks Host object's invariants.
|
||||
Validator m_validator;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/** @class CheckStaticForNoThrow
|
||||
|
||||
@par Exception Safety Level:
|
||||
This exception-checking policy class for StaticChecker asserts if an exception
|
||||
exists. Functions can use this to show they provide the no-throw exception
|
||||
safety guarantee.
|
||||
*/
|
||||
class CheckStaticForNoThrow
|
||||
{
|
||||
public:
|
||||
static inline void Check( void )
|
||||
{
|
||||
assert( !::std::uncaught_exception() );
|
||||
}
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/** @class CheckStaticForNothing
|
||||
|
||||
@par Exception Safety Level:
|
||||
This exception-checking policy class for StaticChecker does nothing when called.
|
||||
Functions can use this to show they might provide the weak exception guarantee.
|
||||
The best guarantee such functions can provide is that nothing gets leaked.
|
||||
*/
|
||||
class CheckStaticForNothing
|
||||
{
|
||||
public:
|
||||
static inline void Check( void ) {}
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/** @class StaticChecker
|
||||
This class checks if a function provides the no-throw exception safety level
|
||||
and if the function violated any invariants. Invariants for stand-alone and
|
||||
static functions act as pre-conditions and post-conditions.
|
||||
|
||||
@par Usage
|
||||
-# Implement a function that checks the invariants associated with a function,
|
||||
or with the static data for a class. The function must
|
||||
have the signature similar to the Validator type. Something like:
|
||||
"static bool Host::StaticIsValid( void );" or "bool IsOkay( void );"
|
||||
- The function should return true if everything is okay, but false if
|
||||
something is wrong.
|
||||
- Or it could assert if anything is wrong.
|
||||
-# If the checker is for static functions within a class, declare typedef's
|
||||
inside the class declaration like these. Make one typedef for each policy
|
||||
you use. I typedef'ed the CheckForNothing policy as CheckInvariants because
|
||||
even if a function can't provide the no-throw guarantee, it should still
|
||||
make sure that static data remains in a valid state.
|
||||
- typedef ::Loki::StaticChecker< ::Loki::CheckForNoThrow > CheckStaticForNoThrow;
|
||||
- typedef ::Loki::StaticChecker< ::Loki::CheckForNothing > CheckStaticInvariants;
|
||||
-# Construct a checker near the top of each member function - except in the
|
||||
validator member function. Pass the address of your validator function into
|
||||
the checker's constructor.
|
||||
- If the function never throws, then use the CheckForNoThrow policy.
|
||||
- Otherwise use the CheckInvariants policy.
|
||||
-# Recompile a debug version of your program, run it, and look for which
|
||||
assertions failed.
|
||||
*/
|
||||
|
||||
template
|
||||
<
|
||||
class ExceptionPolicy
|
||||
>
|
||||
class StaticChecker : public ExceptionPolicy
|
||||
{
|
||||
/// Shorthand for the ExceptionPolicy class.
|
||||
typedef ExceptionPolicy Ep;
|
||||
|
||||
public:
|
||||
|
||||
/// Signature for the validation function.
|
||||
typedef bool ( * Validator )( void );
|
||||
|
||||
/** The constructor makes sure the host is valid at the time the checker
|
||||
was created, thus insuring the host object was not corrupt from the start.
|
||||
*/
|
||||
inline explicit StaticChecker( Validator validator ) :
|
||||
Ep(),
|
||||
m_validator( validator )
|
||||
{
|
||||
Check();
|
||||
}
|
||||
|
||||
/** The destructor checks if any Host invariants failed, and then calls the
|
||||
ExceptionPolicy's Check function to determine what to do in case of an
|
||||
exception.
|
||||
*/
|
||||
inline ~StaticChecker( void )
|
||||
{
|
||||
Check();
|
||||
Ep::Check();
|
||||
}
|
||||
|
||||
/** This first checks its own invariants, and then calls the validator
|
||||
function to make sure no invariants were broken by the function which
|
||||
created this checker. That function can call Check directly to verify
|
||||
the data remains valid at any time.
|
||||
*/
|
||||
inline void Check( void ) const
|
||||
{
|
||||
assert( 0 != this );
|
||||
assert( 0 != m_validator );
|
||||
// Now that this confirms the pointers to the host and validation
|
||||
// functions are not null, go ahead and validate the host object.
|
||||
assert( ( m_validator )() );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/// Default constructor is not implemented.
|
||||
StaticChecker( void );
|
||||
/// Copy constructor is not implemented.
|
||||
StaticChecker( const StaticChecker & );
|
||||
/// Copy-assignment operator is not implemented.
|
||||
StaticChecker & operator = ( const StaticChecker & );
|
||||
|
||||
/// Pointer to member function that checks Host object's invariants.
|
||||
Validator m_validator;
|
||||
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
}; // end namespace Loki
|
||||
|
||||
#endif
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// The Loki Library
|
||||
// Copyright (c) 2008 Rich Sposato
|
||||
// The copyright on this file is protected under the terms of the MIT license.
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software for any
|
||||
// purpose is hereby granted without fee, provided that the above copyright
|
||||
// notice appear in all copies and that both that copyright notice and this
|
||||
// permission notice appear in supporting documentation.
|
||||
//
|
||||
// The author makes no representations about the suitability of this software
|
||||
// for any purpose. It is provided "as is" without express or implied warranty.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// $Id$
|
||||
|
||||
/// @file Checker.h This file provides Loki's Checker facility.
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#ifndef LOKI_CHECKER_H_INCLUDED
|
||||
#define LOKI_CHECKER_H_INCLUDED
|
||||
|
||||
#include <exception> // needed for calls to uncaught_exception.
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
|
||||
/** @par Checker and StaticChecker Overview
|
||||
The Checker and StaticChecker classes have two purposes:
|
||||
- provide a mechanism by which programmers can determine which functions
|
||||
violate class/data invariants,
|
||||
- and determine which exception safety a function provides.
|
||||
|
||||
@par Class & Data Invariants
|
||||
The Checker and StaticChecker utilities define invariants as "expressions that
|
||||
are true for particular data". They uses a function which returns true if all
|
||||
data are valid, and returns false if any datum is invalid. This is called the
|
||||
validator function, and the host class or function provides a pointer to it.
|
||||
The validator could also assert for any invariant which fails rather than
|
||||
return false. If the validator is a static member function, you can use it
|
||||
with checkers in any function, but especially standalone functions and class
|
||||
static functions. If the validator is a non-static member function, you can
|
||||
use it only within non-static member functions.
|
||||
|
||||
@par Exception Safety Levels
|
||||
Years ago, David Abrahams formalized a framework for assessing the exception
|
||||
safety level a function provides. His framework describes three levels of
|
||||
guarantees. Any function which does not provide any of these levels is
|
||||
considered unsafe. Checker and StaticChecker determine a function's safety
|
||||
level through the use of policy classes. Checker's policy classes can show if
|
||||
a function provides any of these three guarantees. (Caveat: Checker can't
|
||||
detect leaks directly by itself, but it can call a validator which does.)
|
||||
StaticChecker's policy classes only provide direct checking for the no-throw
|
||||
and invariant guarantees. With some finesse, a programmer can write a
|
||||
validator for StaticChecker that checks for the Strong guarantee.
|
||||
|
||||
- No-throw guarantee: A function will not throw any exceptions.
|
||||
- Strong guarantee: A function will not change data if an exception occurs.
|
||||
(Also called the no-change guarantee.)
|
||||
- Basic guarantee: A function will not leak resources and data will remain
|
||||
in a valid state if an exception occurs. (Also called a no-leak guarantee.)
|
||||
*/
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/** @class CheckForNoThrow
|
||||
|
||||
@par Exception Safety Level:
|
||||
This exception-checking policy class for Checker asserts if an exception exists.
|
||||
Host classes can use this to show that some member functions provide the no-throw
|
||||
exception safety guarantees.
|
||||
|
||||
@par Requirements For Host Class:
|
||||
This policy imposes no requirements on a host class.
|
||||
*/
|
||||
template < class Host >
|
||||
class CheckForNoThrow
|
||||
{
|
||||
public:
|
||||
|
||||
inline explicit CheckForNoThrow( const Host * ) {}
|
||||
|
||||
inline void Check( const Host * ) const
|
||||
{
|
||||
assert( !::std::uncaught_exception() );
|
||||
}
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/** @class CheckForNoChange
|
||||
|
||||
@par Exception Safety Level:
|
||||
This exception-checking policy class for Checker asserts only if a copy of the
|
||||
host differs from the host object when an exception occurs. Host classes can
|
||||
use this policy to show which member functions provide the strong exception
|
||||
guarantee.
|
||||
|
||||
@par Requirements:
|
||||
This policy requires hosts to provide both the copy-constructor and the
|
||||
equality operator, and is intended for classes with value semantics.
|
||||
equality operator.
|
||||
*/
|
||||
|
||||
template < class Host >
|
||||
class CheckForNoChange
|
||||
{
|
||||
public:
|
||||
|
||||
inline explicit CheckForNoChange( const Host * host ) :
|
||||
m_compare( *host ) {}
|
||||
|
||||
inline void Check( const Host * host ) const
|
||||
{
|
||||
if ( ::std::uncaught_exception() )
|
||||
{
|
||||
assert( m_compare == *host );
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Host m_compare;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/** @class CheckForNoChangeOrThrow
|
||||
|
||||
@par Exception Safety Level:
|
||||
This exception-checking policy class for Checker asserts either if a copy of
|
||||
the host differs from the original host object, or if an exception occurs.
|
||||
Host classes can use this policy to show which member functions provide the
|
||||
no-throw exception guarantee, and would never change data anyway.
|
||||
|
||||
@par Requirements For Host Class:
|
||||
This policy requires hosts to provide both the copy-constructor and the
|
||||
equality operator, and is intended for classes with value semantics.
|
||||
*/
|
||||
|
||||
template < class Host >
|
||||
class CheckForNoChangeOrThrow
|
||||
{
|
||||
public:
|
||||
|
||||
inline explicit CheckForNoChangeOrThrow( const Host * host ) :
|
||||
m_compare( *host ) {}
|
||||
|
||||
inline void Check( const Host * host ) const
|
||||
{
|
||||
assert( !::std::uncaught_exception() );
|
||||
assert( m_compare == *host );
|
||||
}
|
||||
|
||||
private:
|
||||
Host m_compare;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/** @class CheckForEquality
|
||||
|
||||
@par Exception Safety Level:
|
||||
This exception-checking policy class for Checker asserts only if a copy of the
|
||||
host differs from the host object regardless of whether an exception occurs.
|
||||
Host classes can use this policy to show which member functions never change
|
||||
data members, and thereby provide the strong exception safety level by default.
|
||||
|
||||
@par Requirements For Host Class:
|
||||
This policy requires hosts to provide both the copy-constructor and the
|
||||
equality operator, and is intended for classes with value semantics.
|
||||
*/
|
||||
|
||||
template < class Host >
|
||||
class CheckForEquality
|
||||
{
|
||||
public:
|
||||
|
||||
inline explicit CheckForEquality( const Host * host ) :
|
||||
m_compare( *host ) {}
|
||||
|
||||
inline void Check( const Host * host ) const
|
||||
{
|
||||
assert( m_compare == *host );
|
||||
}
|
||||
|
||||
private:
|
||||
Host m_compare;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/** @class CheckForNothing
|
||||
|
||||
@par Exception Safety Level:
|
||||
This exception-checking policy class for Checker does nothing when called.
|
||||
Host classes can use this to show which member functions provide neither the
|
||||
strong nor no-throw exception guarantees. The best guarantee such functions
|
||||
can provide is that nothing gets leaked.
|
||||
|
||||
@par Requirements For Host Class:
|
||||
This policy imposes no requirements on a host class.
|
||||
*/
|
||||
|
||||
template < class Host >
|
||||
class CheckForNothing
|
||||
{
|
||||
public:
|
||||
inline explicit CheckForNothing( const Host * ) {}
|
||||
inline void Check( const Host * ) const {}
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/** @class Checker
|
||||
This class checks if a host class violated an invariant. This asserts if any
|
||||
check for an invariant failed. It can also demonstrate which functions provide
|
||||
which exception safety level.
|
||||
|
||||
@par Usage
|
||||
-# Implement a function that checks each class invariant. The function must
|
||||
have the signature similar to the Validator type. Something like:
|
||||
"bool Host::IsValid( void ) const;"
|
||||
- The function should return true if everything is okay, but false if
|
||||
something is wrong.
|
||||
- Or it could assert if anything is wrong.
|
||||
-# Declare some typedef's inside the class declaration like these. Make one
|
||||
typedef for each exception policy you use. I typedef'ed the CheckForNothing
|
||||
policy as CheckInvariants because even if a function can't provide either the
|
||||
no-throw nor the no-change policies, it should still make sure the object
|
||||
remains in a valid state.
|
||||
- typedef ::Loki::Checker< Host, ::Loki::CheckForNoThrow > CheckForNoThrow;
|
||||
- typedef ::Loki::Checker< Host, ::Loki::CheckForNoChange > CheckForNoChange;
|
||||
- typedef ::Loki::Checker< Host, ::Loki::CheckForEquality > CheckForEquality;
|
||||
- typedef ::Loki::Checker< Host, ::Loki::CheckForNothing > CheckInvariants;
|
||||
-# Construct a checker near the top of each member function - except in the
|
||||
validator member function. Pass the this pointer and the address of your
|
||||
validator function into the checker's constructor.
|
||||
- If the function never throws, then use the CheckForNoThrow policy.
|
||||
- If the function never changes any data members, then use CheckForEquality
|
||||
policy.
|
||||
- If the function's normal execution flow changes data, but must make sure
|
||||
data remains unchanged when any exceptions occur, then use the
|
||||
CheckForNoChange policy.
|
||||
- Otherwise use the CheckInvariants policy.
|
||||
-# Recompile a debug version of your program, run it, and look for which
|
||||
assertions failed.
|
||||
*/
|
||||
|
||||
template
|
||||
<
|
||||
class Host,
|
||||
template < class > class ExceptionPolicy
|
||||
>
|
||||
class Checker : public ExceptionPolicy< Host >
|
||||
{
|
||||
/// Shorthand for the ExceptionPolicy class.
|
||||
typedef ExceptionPolicy< Host > Ep;
|
||||
|
||||
public:
|
||||
|
||||
/// Signature for the validation function.
|
||||
typedef bool ( Host:: * Validator )( void ) const;
|
||||
|
||||
/** The constructor makes sure the host is valid at the time the checker
|
||||
was created, thus insuring the host object was not corrupt from the start.
|
||||
*/
|
||||
inline Checker( const Host * host, Validator validator ) :
|
||||
Ep( host ),
|
||||
m_host( host ),
|
||||
m_validator( validator )
|
||||
{
|
||||
Check();
|
||||
}
|
||||
|
||||
/** The destructor checks if any Host invariants failed, and then calls the
|
||||
ExceptionPolicy's Check function to determine what to do in case of an
|
||||
exception.
|
||||
*/
|
||||
inline ~Checker( void )
|
||||
{
|
||||
Check();
|
||||
Ep::Check( m_host );
|
||||
}
|
||||
|
||||
/** This first checks the invariants for Checker, and then calls the
|
||||
validator function for the host to make sure no class invariants
|
||||
were broken by the host within the Host's member function body. The
|
||||
host member function can call Check directly to verify the object
|
||||
remains valid at any time.
|
||||
*/
|
||||
inline void Check( void ) const
|
||||
{
|
||||
assert( 0 != this );
|
||||
assert( 0 != m_host );
|
||||
assert( 0 != m_validator );
|
||||
// Now that this confirms the pointers to the host and validation
|
||||
// functions are not null, go ahead and validate the host object.
|
||||
assert( ( m_host->*( m_validator ) )() );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/// Default constructor is not implemented.
|
||||
Checker( void );
|
||||
/// Copy constructor is not implemented.
|
||||
Checker( const Checker & );
|
||||
/// Copy-assignment operator is not implemented.
|
||||
Checker & operator = ( const Checker & );
|
||||
|
||||
/// Pointer to the host object.
|
||||
const Host * m_host;
|
||||
|
||||
/// Pointer to member function that checks Host object's invariants.
|
||||
Validator m_validator;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/** @class CheckStaticForNoThrow
|
||||
|
||||
@par Exception Safety Level:
|
||||
This exception-checking policy class for StaticChecker asserts if an exception
|
||||
exists. Functions can use this to show they provide the no-throw exception
|
||||
safety guarantee.
|
||||
*/
|
||||
class CheckStaticForNoThrow
|
||||
{
|
||||
public:
|
||||
static inline void Check( void )
|
||||
{
|
||||
assert( !::std::uncaught_exception() );
|
||||
}
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/** @class CheckStaticForNothing
|
||||
|
||||
@par Exception Safety Level:
|
||||
This exception-checking policy class for StaticChecker does nothing when called.
|
||||
Functions can use this to show they might provide the weak exception guarantee.
|
||||
The best guarantee such functions can provide is that nothing gets leaked.
|
||||
*/
|
||||
class CheckStaticForNothing
|
||||
{
|
||||
public:
|
||||
static inline void Check( void ) {}
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/** @class StaticChecker
|
||||
This class checks if a function provides the no-throw exception safety level
|
||||
and if the function violated any invariants. Invariants for stand-alone and
|
||||
static functions act as pre-conditions and post-conditions.
|
||||
|
||||
@par Usage
|
||||
-# Implement a function that checks the invariants associated with a function,
|
||||
or with the static data for a class. The function must
|
||||
have the signature similar to the Validator type. Something like:
|
||||
"static bool Host::StaticIsValid( void );" or "bool IsOkay( void );"
|
||||
- The function should return true if everything is okay, but false if
|
||||
something is wrong.
|
||||
- Or it could assert if anything is wrong.
|
||||
-# If the checker is for static functions within a class, declare typedef's
|
||||
inside the class declaration like these. Make one typedef for each policy
|
||||
you use. I typedef'ed the CheckForNothing policy as CheckInvariants because
|
||||
even if a function can't provide the no-throw guarantee, it should still
|
||||
make sure that static data remains in a valid state.
|
||||
- typedef ::Loki::StaticChecker< ::Loki::CheckForNoThrow > CheckStaticForNoThrow;
|
||||
- typedef ::Loki::StaticChecker< ::Loki::CheckForNothing > CheckStaticInvariants;
|
||||
-# Construct a checker near the top of each member function - except in the
|
||||
validator member function. Pass the address of your validator function into
|
||||
the checker's constructor.
|
||||
- If the function never throws, then use the CheckForNoThrow policy.
|
||||
- Otherwise use the CheckInvariants policy.
|
||||
-# Recompile a debug version of your program, run it, and look for which
|
||||
assertions failed.
|
||||
*/
|
||||
|
||||
template
|
||||
<
|
||||
class ExceptionPolicy
|
||||
>
|
||||
class StaticChecker : public ExceptionPolicy
|
||||
{
|
||||
/// Shorthand for the ExceptionPolicy class.
|
||||
typedef ExceptionPolicy Ep;
|
||||
|
||||
public:
|
||||
|
||||
/// Signature for the validation function.
|
||||
typedef bool ( * Validator )( void );
|
||||
|
||||
/** The constructor makes sure the host is valid at the time the checker
|
||||
was created, thus insuring the host object was not corrupt from the start.
|
||||
*/
|
||||
inline explicit StaticChecker( Validator validator ) :
|
||||
Ep(),
|
||||
m_validator( validator )
|
||||
{
|
||||
Check();
|
||||
}
|
||||
|
||||
/** The destructor checks if any Host invariants failed, and then calls the
|
||||
ExceptionPolicy's Check function to determine what to do in case of an
|
||||
exception.
|
||||
*/
|
||||
inline ~StaticChecker( void )
|
||||
{
|
||||
Check();
|
||||
Ep::Check();
|
||||
}
|
||||
|
||||
/** This first checks its own invariants, and then calls the validator
|
||||
function to make sure no invariants were broken by the function which
|
||||
created this checker. That function can call Check directly to verify
|
||||
the data remains valid at any time.
|
||||
*/
|
||||
inline void Check( void ) const
|
||||
{
|
||||
assert( 0 != this );
|
||||
assert( 0 != m_validator );
|
||||
// Now that this confirms the pointers to the host and validation
|
||||
// functions are not null, go ahead and validate the host object.
|
||||
assert( ( m_validator )() );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/// Default constructor is not implemented.
|
||||
StaticChecker( void );
|
||||
/// Copy constructor is not implemented.
|
||||
StaticChecker( const StaticChecker & );
|
||||
/// Copy-assignment operator is not implemented.
|
||||
StaticChecker & operator = ( const StaticChecker & );
|
||||
|
||||
/// Pointer to member function that checks Host object's invariants.
|
||||
Validator m_validator;
|
||||
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
}; // end namespace Loki
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,204 +1,204 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The Loki Library
|
||||
// Copyright (c) 2006 by Guillaume Chatelet
|
||||
//
|
||||
// Code covered by the MIT License
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software for any
|
||||
// purpose is hereby granted without fee, provided that the above copyright
|
||||
// notice appear in all copies and that both that copyright notice and this
|
||||
// permission notice appear in supporting documentation.
|
||||
//
|
||||
// The authors make no representations about the suitability of this software
|
||||
// for any purpose. It is provided "as is" without express or implied warranty.
|
||||
//
|
||||
// This code DOES NOT accompany the book:
|
||||
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// $Id$
|
||||
|
||||
#ifndef SPCACHEDFACTORY_H_
|
||||
#define SPCACHEDFACTORY_H_
|
||||
|
||||
/**
|
||||
* This file is intented to be used if you want a CachedFactory with
|
||||
* a SmartPointer encapsulation policy.
|
||||
* It as been defined in a separate file because of the many introduced
|
||||
* dependencies (SmartPtr.h would depend on Functor.h and CachedFactory.h
|
||||
* would depend on SmartPtr.h). By defining another header you pay for those
|
||||
* extra dependencies only if you need it.
|
||||
*
|
||||
* This file defines FunctionStorage a new SmartPointer storage policy and
|
||||
* SmartPointer a new CachedFactory encapsulation policy.
|
||||
*/
|
||||
|
||||
#include <loki/Functor.h>
|
||||
#include <loki/SmartPtr.h>
|
||||
#include <loki/CachedFactory.h>
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \class FunctionStorage
|
||||
///
|
||||
/// \ingroup SmartPointerStorageGroup
|
||||
/// \brief Implementation of the StoragePolicy used by SmartPtr.
|
||||
///
|
||||
/// This storage policy is used by SmartPointer CachedFactory's encapsulation
|
||||
/// policy. It's purpose is to call a Functor instead of deleting the
|
||||
/// underlying pointee object. You have to set the callback functor by calling
|
||||
/// SetCallBackFunction(const FunctorType &functor).
|
||||
///
|
||||
/// Unfortunately, the functor argument is not a reference to the SmartPtr but
|
||||
/// a void *. Making functor argument a reference to the pointer would require
|
||||
/// the FunctionStorage template to know the full definition of the SmartPtr.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T>
|
||||
class FunctionStorage
|
||||
{
|
||||
public:
|
||||
/// the type of the pointee_ object
|
||||
typedef T* StoredType;
|
||||
/// type used to declare OwnershipPolicy type.
|
||||
typedef T* InitPointerType;
|
||||
/// type returned by operator->
|
||||
typedef T* PointerType;
|
||||
/// type returned by operator*
|
||||
typedef T& ReferenceType;
|
||||
/// type of the Functor to set
|
||||
typedef Functor< void , Seq< void* > > FunctorType;
|
||||
|
||||
FunctionStorage() : pointee_(Default()), functor_()
|
||||
{}
|
||||
|
||||
// The storage policy doesn't initialize the stored pointer
|
||||
// which will be initialized by the OwnershipPolicy's Clone fn
|
||||
FunctionStorage(const FunctionStorage& rsh) : pointee_(0), functor_(rsh.functor_)
|
||||
{}
|
||||
|
||||
template <class U>
|
||||
FunctionStorage(const FunctionStorage<U>& rsh) : pointee_(0), functor_(rsh.functor_)
|
||||
{}
|
||||
|
||||
FunctionStorage(const StoredType& p) : pointee_(p), functor_() {}
|
||||
|
||||
PointerType operator->() const { return pointee_; }
|
||||
|
||||
ReferenceType operator*() const { return *pointee_; }
|
||||
|
||||
void Swap(FunctionStorage& rhs)
|
||||
{
|
||||
std::swap(pointee_, rhs.pointee_);
|
||||
std::swap(functor_, rhs.functor_);
|
||||
}
|
||||
|
||||
/// Sets the callback function to call. You have to specify it or
|
||||
/// the smartPtr will throw a bad_function_call exception.
|
||||
void SetCallBackFunction(const FunctorType &functor)
|
||||
{
|
||||
functor_ = functor;
|
||||
}
|
||||
|
||||
// Accessors
|
||||
template <class F>
|
||||
friend typename FunctionStorage<F>::PointerType GetImpl(const FunctionStorage<F>& sp);
|
||||
|
||||
template <class F>
|
||||
friend const typename FunctionStorage<F>::StoredType& GetImplRef(const FunctionStorage<F>& sp);
|
||||
|
||||
template <class F>
|
||||
friend typename FunctionStorage<F>::StoredType& GetImplRef(FunctionStorage<F>& sp);
|
||||
|
||||
protected:
|
||||
// Destroys the data stored
|
||||
// (Destruction might be taken over by the OwnershipPolicy)
|
||||
void Destroy()
|
||||
{
|
||||
functor_(this);
|
||||
}
|
||||
|
||||
// Default value to initialize the pointer
|
||||
static StoredType Default()
|
||||
{ return 0; }
|
||||
|
||||
private:
|
||||
// Data
|
||||
StoredType pointee_;
|
||||
FunctorType functor_;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
inline typename FunctionStorage<T>::PointerType GetImpl(const FunctionStorage<T>& sp)
|
||||
{ return sp.pointee_; }
|
||||
|
||||
template <class T>
|
||||
inline const typename FunctionStorage<T>::StoredType& GetImplRef(const FunctionStorage<T>& sp)
|
||||
{ return sp.pointee_; }
|
||||
|
||||
template <class T>
|
||||
inline typename FunctionStorage<T>::StoredType& GetImplRef(FunctionStorage<T>& sp)
|
||||
{ return sp.pointee_; }
|
||||
|
||||
/**
|
||||
* \class SmartPointer
|
||||
* \ingroup EncapsulationPolicyCachedFactoryGroup
|
||||
* \brief Encapsulate the object in a SmartPtr with FunctionStorage policy.
|
||||
*
|
||||
* The object will come back to the Cache as soon as no more SmartPtr are
|
||||
* referencing this object. You can customize the SmartPointer with the standard
|
||||
* SmartPtr policies (OwnershipPolicy, ConversionPolicy, CheckingPolicy,
|
||||
* ConstnessPolicy) but StoragePolicy is forced to FunctionStorage.
|
||||
*/
|
||||
template
|
||||
<
|
||||
class AbstractProduct,
|
||||
template <class> class OwnershipPolicy = RefCounted,
|
||||
class ConversionPolicy = DisallowConversion,
|
||||
template <class> class CheckingPolicy = AssertCheck,
|
||||
template<class> class ConstnessPolicy = LOKI_DEFAULT_CONSTNESS
|
||||
>
|
||||
class SmartPointer
|
||||
{
|
||||
private:
|
||||
typedef SmartPtr< AbstractProduct,OwnershipPolicy,
|
||||
ConversionPolicy, CheckingPolicy,
|
||||
FunctionStorage, ConstnessPolicy > CallBackSP;
|
||||
protected:
|
||||
typedef CallBackSP ProductReturn;
|
||||
SmartPointer() : fun(this, &SmartPointer::smartPointerCallbackFunction) {}
|
||||
virtual ~SmartPointer(){}
|
||||
|
||||
ProductReturn encapsulate(AbstractProduct* pProduct)
|
||||
{
|
||||
CallBackSP SP(pProduct);
|
||||
SP.SetCallBackFunction(fun);
|
||||
return SP;
|
||||
}
|
||||
|
||||
AbstractProduct* release(ProductReturn &pProduct)
|
||||
{
|
||||
return GetImpl(pProduct);
|
||||
}
|
||||
|
||||
const char* name(){return "smart pointer";}
|
||||
|
||||
private:
|
||||
SmartPointer& operator=(const SmartPointer&);
|
||||
SmartPointer(const SmartPointer&);
|
||||
void smartPointerCallbackFunction(void* pSP)
|
||||
{
|
||||
CallBackSP &SP(*reinterpret_cast<CallBackSP*>(pSP));
|
||||
ReleaseObject(SP);
|
||||
}
|
||||
virtual void ReleaseObject(ProductReturn &object)=0;
|
||||
const typename CallBackSP::FunctorType fun;
|
||||
};
|
||||
|
||||
} // namespace Loki
|
||||
|
||||
#endif /*SPCACHEDFACTORY_H_*/
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The Loki Library
|
||||
// Copyright (c) 2006 by Guillaume Chatelet
|
||||
//
|
||||
// Code covered by the MIT License
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software for any
|
||||
// purpose is hereby granted without fee, provided that the above copyright
|
||||
// notice appear in all copies and that both that copyright notice and this
|
||||
// permission notice appear in supporting documentation.
|
||||
//
|
||||
// The authors make no representations about the suitability of this software
|
||||
// for any purpose. It is provided "as is" without express or implied warranty.
|
||||
//
|
||||
// This code DOES NOT accompany the book:
|
||||
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// $Id$
|
||||
|
||||
#ifndef SPCACHEDFACTORY_H_
|
||||
#define SPCACHEDFACTORY_H_
|
||||
|
||||
/**
|
||||
* This file is intented to be used if you want a CachedFactory with
|
||||
* a SmartPointer encapsulation policy.
|
||||
* It as been defined in a separate file because of the many introduced
|
||||
* dependencies (SmartPtr.h would depend on Functor.h and CachedFactory.h
|
||||
* would depend on SmartPtr.h). By defining another header you pay for those
|
||||
* extra dependencies only if you need it.
|
||||
*
|
||||
* This file defines FunctionStorage a new SmartPointer storage policy and
|
||||
* SmartPointer a new CachedFactory encapsulation policy.
|
||||
*/
|
||||
|
||||
#include <loki/Functor.h>
|
||||
#include <loki/SmartPtr.h>
|
||||
#include <loki/CachedFactory.h>
|
||||
|
||||
namespace Loki
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \class FunctionStorage
|
||||
///
|
||||
/// \ingroup SmartPointerStorageGroup
|
||||
/// \brief Implementation of the StoragePolicy used by SmartPtr.
|
||||
///
|
||||
/// This storage policy is used by SmartPointer CachedFactory's encapsulation
|
||||
/// policy. It's purpose is to call a Functor instead of deleting the
|
||||
/// underlying pointee object. You have to set the callback functor by calling
|
||||
/// SetCallBackFunction(const FunctorType &functor).
|
||||
///
|
||||
/// Unfortunately, the functor argument is not a reference to the SmartPtr but
|
||||
/// a void *. Making functor argument a reference to the pointer would require
|
||||
/// the FunctionStorage template to know the full definition of the SmartPtr.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T>
|
||||
class FunctionStorage
|
||||
{
|
||||
public:
|
||||
/// the type of the pointee_ object
|
||||
typedef T* StoredType;
|
||||
/// type used to declare OwnershipPolicy type.
|
||||
typedef T* InitPointerType;
|
||||
/// type returned by operator->
|
||||
typedef T* PointerType;
|
||||
/// type returned by operator*
|
||||
typedef T& ReferenceType;
|
||||
/// type of the Functor to set
|
||||
typedef Functor< void , Seq< void* > > FunctorType;
|
||||
|
||||
FunctionStorage() : pointee_(Default()), functor_()
|
||||
{}
|
||||
|
||||
// The storage policy doesn't initialize the stored pointer
|
||||
// which will be initialized by the OwnershipPolicy's Clone fn
|
||||
FunctionStorage(const FunctionStorage& rsh) : pointee_(0), functor_(rsh.functor_)
|
||||
{}
|
||||
|
||||
template <class U>
|
||||
FunctionStorage(const FunctionStorage<U>& rsh) : pointee_(0), functor_(rsh.functor_)
|
||||
{}
|
||||
|
||||
FunctionStorage(const StoredType& p) : pointee_(p), functor_() {}
|
||||
|
||||
PointerType operator->() const { return pointee_; }
|
||||
|
||||
ReferenceType operator*() const { return *pointee_; }
|
||||
|
||||
void Swap(FunctionStorage& rhs)
|
||||
{
|
||||
std::swap(pointee_, rhs.pointee_);
|
||||
std::swap(functor_, rhs.functor_);
|
||||
}
|
||||
|
||||
/// Sets the callback function to call. You have to specify it or
|
||||
/// the smartPtr will throw a bad_function_call exception.
|
||||
void SetCallBackFunction(const FunctorType &functor)
|
||||
{
|
||||
functor_ = functor;
|
||||
}
|
||||
|
||||
// Accessors
|
||||
template <class F>
|
||||
friend typename FunctionStorage<F>::PointerType GetImpl(const FunctionStorage<F>& sp);
|
||||
|
||||
template <class F>
|
||||
friend const typename FunctionStorage<F>::StoredType& GetImplRef(const FunctionStorage<F>& sp);
|
||||
|
||||
template <class F>
|
||||
friend typename FunctionStorage<F>::StoredType& GetImplRef(FunctionStorage<F>& sp);
|
||||
|
||||
protected:
|
||||
// Destroys the data stored
|
||||
// (Destruction might be taken over by the OwnershipPolicy)
|
||||
void Destroy()
|
||||
{
|
||||
functor_(this);
|
||||
}
|
||||
|
||||
// Default value to initialize the pointer
|
||||
static StoredType Default()
|
||||
{ return 0; }
|
||||
|
||||
private:
|
||||
// Data
|
||||
StoredType pointee_;
|
||||
FunctorType functor_;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
inline typename FunctionStorage<T>::PointerType GetImpl(const FunctionStorage<T>& sp)
|
||||
{ return sp.pointee_; }
|
||||
|
||||
template <class T>
|
||||
inline const typename FunctionStorage<T>::StoredType& GetImplRef(const FunctionStorage<T>& sp)
|
||||
{ return sp.pointee_; }
|
||||
|
||||
template <class T>
|
||||
inline typename FunctionStorage<T>::StoredType& GetImplRef(FunctionStorage<T>& sp)
|
||||
{ return sp.pointee_; }
|
||||
|
||||
/**
|
||||
* \class SmartPointer
|
||||
* \ingroup EncapsulationPolicyCachedFactoryGroup
|
||||
* \brief Encapsulate the object in a SmartPtr with FunctionStorage policy.
|
||||
*
|
||||
* The object will come back to the Cache as soon as no more SmartPtr are
|
||||
* referencing this object. You can customize the SmartPointer with the standard
|
||||
* SmartPtr policies (OwnershipPolicy, ConversionPolicy, CheckingPolicy,
|
||||
* ConstnessPolicy) but StoragePolicy is forced to FunctionStorage.
|
||||
*/
|
||||
template
|
||||
<
|
||||
class AbstractProduct,
|
||||
template <class> class OwnershipPolicy = RefCounted,
|
||||
class ConversionPolicy = DisallowConversion,
|
||||
template <class> class CheckingPolicy = AssertCheck,
|
||||
template<class> class ConstnessPolicy = LOKI_DEFAULT_CONSTNESS
|
||||
>
|
||||
class SmartPointer
|
||||
{
|
||||
private:
|
||||
typedef SmartPtr< AbstractProduct,OwnershipPolicy,
|
||||
ConversionPolicy, CheckingPolicy,
|
||||
FunctionStorage, ConstnessPolicy > CallBackSP;
|
||||
protected:
|
||||
typedef CallBackSP ProductReturn;
|
||||
SmartPointer() : fun(this, &SmartPointer::smartPointerCallbackFunction) {}
|
||||
virtual ~SmartPointer(){}
|
||||
|
||||
ProductReturn encapsulate(AbstractProduct* pProduct)
|
||||
{
|
||||
CallBackSP SP(pProduct);
|
||||
SP.SetCallBackFunction(fun);
|
||||
return SP;
|
||||
}
|
||||
|
||||
AbstractProduct* release(ProductReturn &pProduct)
|
||||
{
|
||||
return GetImpl(pProduct);
|
||||
}
|
||||
|
||||
const char* name(){return "smart pointer";}
|
||||
|
||||
private:
|
||||
SmartPointer& operator=(const SmartPointer&);
|
||||
SmartPointer(const SmartPointer&);
|
||||
void smartPointerCallbackFunction(void* pSP)
|
||||
{
|
||||
CallBackSP &SP(*reinterpret_cast<CallBackSP*>(pSP));
|
||||
ReleaseObject(SP);
|
||||
}
|
||||
virtual void ReleaseObject(ProductReturn &object)=0;
|
||||
const typename CallBackSP::FunctorType fun;
|
||||
};
|
||||
|
||||
} // namespace Loki
|
||||
|
||||
#endif /*SPCACHEDFACTORY_H_*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue