You can subscribe to this list here.
2005 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(80) |
Aug
(36) |
Sep
(120) |
Oct
(89) |
Nov
(57) |
Dec
(22) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2006 |
Jan
(308) |
Feb
(66) |
Mar
(88) |
Apr
(54) |
May
(43) |
Jun
(40) |
Jul
(33) |
Aug
(1) |
Sep
(7) |
Oct
(65) |
Nov
(19) |
Dec
(10) |
2007 |
Jan
(5) |
Feb
(8) |
Mar
(7) |
Apr
|
May
(7) |
Jun
|
Jul
(5) |
Aug
(3) |
Sep
(1) |
Oct
|
Nov
|
Dec
|
2008 |
Jan
|
Feb
|
Mar
(5) |
Apr
|
May
(5) |
Jun
(21) |
Jul
(27) |
Aug
(6) |
Sep
|
Oct
(1) |
Nov
(5) |
Dec
(10) |
2009 |
Jan
(67) |
Feb
(3) |
Mar
(26) |
Apr
(2) |
May
|
Jun
(1) |
Jul
|
Aug
(2) |
Sep
(10) |
Oct
(18) |
Nov
(20) |
Dec
(3) |
2010 |
Jan
|
Feb
|
Mar
(1) |
Apr
(1) |
May
|
Jun
|
Jul
|
Aug
|
Sep
(9) |
Oct
(3) |
Nov
|
Dec
|
2011 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(7) |
Jul
|
Aug
|
Sep
(39) |
Oct
(43) |
Nov
(7) |
Dec
|
2012 |
Jan
|
Feb
|
Mar
|
Apr
(6) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2013 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(7) |
Jul
|
Aug
(1) |
Sep
|
Oct
|
Nov
|
Dec
|
From: <ric...@us...> - 2013-08-06 22:56:33
|
Revision: 1191 http://sourceforge.net/p/loki-lib/code/1191 Author: rich_sposato Date: 2013-08-06 22:56:31 +0000 (Tue, 06 Aug 2013) Log Message: ----------- Improved SmartAssert component. Modified Paths: -------------- trunk/Loki.sln trunk/include/loki/SmartAssert.hpp trunk/src/SmartAssert.cpp trunk/test/SmartAssert/SmartAssert.cbp trunk/test/SmartAssert/main.cpp Modified: trunk/Loki.sln =================================================================== --- trunk/Loki.sln 2013-06-24 06:10:50 UTC (rev 1190) +++ trunk/Loki.sln 2013-08-06 22:56:31 UTC (rev 1191) @@ -115,8 +115,6 @@ {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} = {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ThreadLocal", "test\ThreadLocal\ThreadLocal.vcxproj", "{27CB0BB1-1754-46AB-A8C6-697D1B9B9C41}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Lockable", "test\Lockable\Lockable.vcxproj", "{22A34627-1480-4180-A8B6-4C05E77E27F8}" ProjectSection(ProjectDependencies) = postProject {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} = {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} @@ -127,13 +125,15 @@ {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} = {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "library", "src\Library.vcxproj", "{CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Library", "src\Library.vcxproj", "{CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SmartAssert", "test\SmartAssert\SmartAssert.vcxproj", "{DA7BBAE5-1C1A-4B5E-ABF1-2B5090DB2988}" ProjectSection(ProjectDependencies) = postProject {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} = {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ThreadLocal", "test\ThreadLocal\ThreadLocal.vcxproj", "{27CB0BB1-1754-46AB-A8C6-697D1B9B9C41}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -232,10 +232,6 @@ {0605A820-D075-48AC-ABB6-D3FF05D5CD1F}.Debug|Win32.Build.0 = Debug|Win32 {0605A820-D075-48AC-ABB6-D3FF05D5CD1F}.Release|Win32.ActiveCfg = Release|Win32 {0605A820-D075-48AC-ABB6-D3FF05D5CD1F}.Release|Win32.Build.0 = Release|Win32 - {27CB0BB1-1754-46AB-A8C6-697D1B9B9C41}.Debug|Win32.ActiveCfg = Debug|Win32 - {27CB0BB1-1754-46AB-A8C6-697D1B9B9C41}.Debug|Win32.Build.0 = Debug|Win32 - {27CB0BB1-1754-46AB-A8C6-697D1B9B9C41}.Release|Win32.ActiveCfg = Release|Win32 - {27CB0BB1-1754-46AB-A8C6-697D1B9B9C41}.Release|Win32.Build.0 = Release|Win32 {22A34627-1480-4180-A8B6-4C05E77E27F8}.Debug|Win32.ActiveCfg = Debug|Win32 {22A34627-1480-4180-A8B6-4C05E77E27F8}.Debug|Win32.Build.0 = Debug|Win32 {22A34627-1480-4180-A8B6-4C05E77E27F8}.Release|Win32.ActiveCfg = Release|Win32 @@ -252,6 +248,10 @@ {DA7BBAE5-1C1A-4B5E-ABF1-2B5090DB2988}.Debug|Win32.Build.0 = Debug|Win32 {DA7BBAE5-1C1A-4B5E-ABF1-2B5090DB2988}.Release|Win32.ActiveCfg = Release|Win32 {DA7BBAE5-1C1A-4B5E-ABF1-2B5090DB2988}.Release|Win32.Build.0 = Release|Win32 + {27CB0BB1-1754-46AB-A8C6-697D1B9B9C41}.Debug|Win32.ActiveCfg = Debug|Win32 + {27CB0BB1-1754-46AB-A8C6-697D1B9B9C41}.Debug|Win32.Build.0 = Debug|Win32 + {27CB0BB1-1754-46AB-A8C6-697D1B9B9C41}.Release|Win32.ActiveCfg = Release|Win32 + {27CB0BB1-1754-46AB-A8C6-697D1B9B9C41}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE Modified: trunk/include/loki/SmartAssert.hpp =================================================================== --- trunk/include/loki/SmartAssert.hpp 2013-06-24 06:10:50 UTC (rev 1190) +++ trunk/include/loki/SmartAssert.hpp 2013-08-06 22:56:31 UTC (rev 1191) @@ -104,8 +104,8 @@ @endcode @par Setting the Severity Level - Assertions treat all error conditions as an excuse to commit suicide. That - one-size-fits-all solution seems overly drastic for minor errors. At least + Typical assertions treat all error conditions as an excuse to commit suicide. + That one-size-fits-all solution seems overly drastic for minor errors. At least SmartAssert gives the developer more detailed output to help understand why the program died. @@ -153,20 +153,15 @@ @par Write Your Own Policy. Many parts of Loki were implemented using policy-based software design, and SmartAssert follows that tradition. SmartAssert has a default policy that - mimics the behaviors of assert. If you want to make your own policy class, - write that class to have the same function signatures as - CommandLineAssertPolicy, and use the LOKI_SMART_ASSERT_POLICIED macro instead - of LOKI_SMART_ASSERT. + mimics the behaviors of assert. You can implement your own policies to handle + assertions by making a class with the function signatures shown below. If you + write your own policy class, you should also use the LOKI_SMART_ASSERT_POLICIED + macro, and not the LOKI_SMART_ASSERT macro. - @par Potential Policies - - To call a special debugger rather than the default one. - - To send output to a log file instead of to cout. - - To create a popup dialog box to ask the user. - - To attempt last moment cleanup before the program dies. - @code class MyPolicy { + static bool FixedProblem( const SmartAssertBase * asserter ); static void Output( const SmartAssertBase * asserter ); static void Debugger( const SmartAssertBase * asserter ); static SmartAssertBase::UserResponse AskUser( const SmartAssertBase * asserter ); @@ -175,6 +170,16 @@ LOKI_SMART_ASSERT_POLICIED( cond, MyPolicy ); @endcode + @par Potential Policies You Can Create + - To provide a different output message than the default one. + - To call a special debugger rather than the default one. + - To send output to a log file, syslog, or cout, instead of to cerr. + - To create a popup dialog box to ask the user. + - To attempt last moment cleanup before the program dies. + - To correct the problem. + - To fix data invariants caused by the problem. + - Handle assertion by throwing exception. + @par Thread Safety. Each SmartAssert object is declared locally within a function, so it is only accessible by the thread executing it. However, each SmartAssert makes its @@ -239,6 +244,7 @@ LongDouble }; + /// Provides human readable name of data type. static const char * GetName( DataTypeTag tag ); /// @union DataValue Can be configured as any primitive data type. @@ -285,7 +291,11 @@ DataValue( const double v ) : m_double( v ) {} DataValue( const long double v ) : m_l_double( v ) {} - void Output( DataTypeTag type ) const; + /** Sends output of datatype and value to cerr or cout. + @param type What type of data is in the union. + @param use_cerr True to send output to standard error instead of standard out. + */ + void Output( DataTypeTag type, bool use_cerr ) const; }; AssertInfo() : m_type( Unknown ), m_value(), m_next( nullptr ) {} @@ -309,11 +319,13 @@ AssertInfo( double v ) : m_type( Double ), m_value( v ), m_next( nullptr ) {} AssertInfo( long double v ) : m_type( LongDouble ), m_value( v ), m_next( nullptr ) {} - /// Function provides default output action. - void Output() const; + /** Provides default output action. + @param use_cerr True to send output to standard error instead of standard out. + */ + void Output( bool use_cerr ) const; - DataTypeTag m_type; ///< What type of data this stores. - DataValue m_value; ///< Value of that data. + DataTypeTag m_type; ///< What type of data this stores. + DataValue m_value; ///< Value of that data. mutable const AssertInfo * m_next; ///< Pointer to next piece of info, if any. }; @@ -337,7 +349,7 @@ AssertContext( const char * description, const char * value ); /// Function provides default output action. - void Output() const; + void Output( bool use_cerr ) const; unsigned int m_line; ///< Line number within file. const char * m_value; ///< Pointer to either filename or function name. @@ -383,14 +395,16 @@ static const char * const LineDesc; static const char * const FunctionDesc; - mutable const AssertContext * m_context; /// Linked-list of contexts of where assertion occurred. - mutable const AssertInfo * m_info; ///< Linked-list of values provided for output purposes. - SeverityLevel m_level; ///< How bad is this assertion? - bool * m_ignore; ///< Pointer to ignore-always flag. - const char * m_expression; ///< Pointer to C-style string of failed assertion expression. - const char * m_message; ///< Simple message made by developer. - bool m_handled; ///< True if this assertion was handled before destructor. + /// @note All the variables are public so developers can access them through policy classes. + mutable const AssertContext * m_context; ///< Linked-list of contexts of where assertion occurred. + mutable const AssertInfo * m_info; ///< Linked-list of values provided for output purposes. + SeverityLevel m_level; ///< How bad is this assertion? + bool * m_ignore; ///< Pointer to ignore-always flag. + const char * m_expression; ///< Pointer to C-style string of failed assertion expression. + const char * m_message; ///< Simple message made by developer. + bool m_handled; ///< True if this assertion was handled before destructor. + protected: /// Default constructor is used for release builds. It ignores assertions. @@ -414,34 +428,38 @@ /// Called to handle assertion failure. void HandleFailure(); - /// Default implementation of code to output information about assertion. +private: + + /// @note Virtual functions are private to prevent policy classes from using them. + + /// Calls policy class to find out if host program fixed problem. + virtual bool FixedProblem() const = 0; + + /// Calls policy class to output information about assertion. virtual void CallOutput() const; - /// Default implementation of code to call debugger. - virtual void CallDebugger() const; + /// Calls policy class to invoke debugger. + virtual void CallDebugger() const = 0; - /// Default implementation of code to ask user what to do. - virtual UserResponse AskUser() const; + /// Calls policy class to ask user what to do. + virtual UserResponse AskUser() const = 0; - /// Default implementation of code to abort program. + /// Calls policy class to abort program. virtual void AbortNow() const; - - /// Ignore-always flag used by assertions created in release builds. - static bool s_alwaysIgnore; }; // --------------------------------------------------------------------- -/** @class CommandLineAssertPolicy Default policy for command line programs. - Developers can implement their own policies to handle assertions by making a - class with the same function signatures as this class. If you write your own - policy class, you should also use the LOKI_SMART_ASSERT_POLICIED macro, and - not the LOKI_SMART_ASSERT macro. +/** @class CoutAssertPolicy This is a policy for command line programs. It + sends assertion messages to the standard output stream, std::cout. */ -class CommandLineAssertPolicy +class CoutAssertPolicy { public: + /// SmartAssert will ignore error if this returns true. + static bool FixedProblem( const SmartAssertBase * asserter ); + /// Displays information about assertion to the user. static void Output( const SmartAssertBase * asserter ); @@ -458,6 +476,24 @@ // --------------------------------------------------------------------- +/** @class CerrAssertPolicy This is a policy for command line programs. It + sends assertion messages to the standard error stream, std::cerr. This is + the default policy for SmartAssert. +*/ +class CerrAssertPolicy : public CoutAssertPolicy +{ +public: + + /// Displays information about assertion to the user. + static void Output( const SmartAssertBase * asserter ); + + /// Asks user how to handle assertion. + static SmartAssertBase::UserResponse AskUser( const SmartAssertBase * asserter ); + +}; + +// --------------------------------------------------------------------- + /** @class class SmartAssert */ template< class AssertPolicy > @@ -486,7 +522,10 @@ /// Called to do non-default actions when assertion fails. void operator ()() { HandleFailure(); } - /// Adds one piece of information to assertion, generally a variable or result of function call. + /** Adds one piece of information to assertion, generally a variable or result of function call. + This function relies on conversion constructors in AssertInfo to create an AssertInfo from a + single variable. + */ SmartAssert & operator ()( const AssertInfo & info ) { return static_cast< SmartAssert & >( AddInfo( info ) ); @@ -500,21 +539,33 @@ private: + /// @note Virtual functions are private to prevent policy classes from using them. + + /// Calls policy class to find out if host program fixed problem. + virtual bool FixedProblem() const + { + return AssertPolicy::FixedProblem( dynamic_cast< const SmartAssertBase * >( this ) ); + } + + /// Calls policy class to output information about assertion. virtual void CallOutput() const { AssertPolicy::Output( dynamic_cast< const SmartAssertBase * >( this ) ); } + /// Calls policy class to invoke debugger. virtual void CallDebugger() const { AssertPolicy::Debugger( dynamic_cast< const SmartAssertBase * >( this ) ); } + /// Calls policy class to ask user what to do. virtual SmartAssertBase::UserResponse AskUser() const { return AssertPolicy::AskUser( dynamic_cast< const SmartAssertBase * >( this ) ); } + /// Calls policy class to abort program. virtual void AbortNow() const { AssertPolicy::AbortNow( dynamic_cast< const SmartAssertBase * >( this ) ); @@ -603,9 +654,9 @@ #define LOKI_MAKE_SMART_ASSERT( class_name, ignore_var_name, expr ) \ static bool ignore_var_name = false; \ - class class_name : public ::Loki::SmartAssert< ::Loki::CommandLineAssertPolicy > \ + class class_name : public ::Loki::SmartAssert< ::Loki::CerrAssertPolicy > \ { public: \ - typedef ::Loki::SmartAssert< ::Loki::CommandLineAssertPolicy > BaseClass; \ + typedef ::Loki::SmartAssert< ::Loki::CerrAssertPolicy > BaseClass; \ class_name( bool * ignore, const char * expression ) \ : BaseClass( ignore, expression ) {} \ virtual ~class_name() {} \ @@ -621,7 +672,7 @@ #else #define LOKI_SMART_ASSERT( expr ) \ if ( true ) ; else \ - ::Loki::SmartAssert< ::Loki::CommandLineAssertPolicy >() + ::Loki::SmartAssert< ::Loki::CerrAssertPolicy >() // Do nothing. Compiler should optimize away the else branch. #endif Modified: trunk/src/SmartAssert.cpp =================================================================== --- trunk/src/SmartAssert.cpp 2013-06-24 06:10:50 UTC (rev 1190) +++ trunk/src/SmartAssert.cpp 2013-08-06 22:56:31 UTC (rev 1191) @@ -51,7 +51,7 @@ namespace Loki { -bool SmartAssertBase::s_alwaysIgnore = true; +static bool s_alwaysIgnore = true; const char * const SmartAssertBase::FileDesc = "file"; const char * const SmartAssertBase::LineDesc = "line"; @@ -92,119 +92,121 @@ // --------------------------------------------------------------------- -void AssertInfo::DataValue::Output( DataTypeTag theType ) const +void AssertInfo::DataValue::Output( DataTypeTag theType, bool use_cerr ) const { + ::std::basic_ostream< char > & out = ( use_cerr ) ? ::std::cerr : ::std::cout; + switch ( theType ) { case Unknown: { - cout << "\t Error! Unknown data type! " << theType; + out << "\t Error! Unknown data type! " << theType; break; } case Boolean: { const char * message = m_bool ? "true" : "false"; - cout << message; + out << message; break; } case JustChar: { - cout << m_char; + out << m_char; break; } case SignedChar: { - cout << m_s_char; + out << m_s_char; break; } case UnsignedChar: { - cout << m_u_char; + out << m_u_char; break; } case SignedShort: { - cout << m_s_short; + out << m_s_short; break; } case UnsignedShort: { - cout << m_u_short; + out << m_u_short; break; } case JustInt: { - cout << m_int; + out << m_int; break; } case SignedInt: { - cout << m_int; + out << m_int; break; } case UnsignedInt: { - cout << m_u_int; + out << m_u_int; break; } case Long: { - cout << m_long; + out << m_long; break; } case UnsignedLong: { - cout << m_u_long; + out << m_u_long; break; } case LongInt: { - cout << m_s_long_int; + out << m_s_long_int; break; } case UnsignedLongInt: { - cout << m_u_long_int; + out << m_u_long_int; break; } case CharPtr: { - cout << m_p_char; + out << m_p_char; break; } case SignedCharPtr: { - cout << m_p_s_char; + out << m_p_s_char; break; } case UnsignedCharPtr: { - cout << m_p_u_char; + out << m_p_u_char; break; } case VoidPtr: { - cout << m_p_v; + out << m_p_v; break; } case Float: { - cout << m_float; + out << m_float; break; } case Double: { - cout << m_double; + out << m_double; break; } case LongDouble: { - cout << m_l_double; + out << m_l_double; break; } default: { - cout << "\t Error! Undefined data type! " << theType; + out << "\t Error! Undefined data type! " << theType; break; } } @@ -212,11 +214,12 @@ // --------------------------------------------------------------------- -void AssertInfo::Output() const +void AssertInfo::Output( bool use_cerr ) const { - cout << "\t" << GetName( m_type ) << ": "; - m_value.Output( m_type ); - cout << endl; + ::std::basic_ostream< char > & out = ( use_cerr ) ? ::std::cerr : ::std::cout; + out << "\t" << GetName( m_type ) << ": "; + m_value.Output( m_type, use_cerr ); + out << endl; } // --------------------------------------------------------------------- @@ -241,16 +244,17 @@ // --------------------------------------------------------------------- -void AssertContext::Output() const +void AssertContext::Output( bool use_cerr ) const { - cout << m_description << ": "; + ::std::basic_ostream< char > & out = ( use_cerr ) ? ::std::cerr : ::std::cout; + out << m_description << ": "; if ( m_value != nullptr ) { - cout << m_value; + out << m_value; } else { - cout << m_line; + out << m_line; } } @@ -354,28 +358,14 @@ void SmartAssertBase::CallOutput() const { - CommandLineAssertPolicy::Output( this ); + CerrAssertPolicy::Output( this ); } // --------------------------------------------------------------------- -void SmartAssertBase::CallDebugger() const -{ - CommandLineAssertPolicy::Debugger( this ); -} - -// --------------------------------------------------------------------- - -SmartAssertBase::UserResponse SmartAssertBase::AskUser() const -{ - return CommandLineAssertPolicy::AskUser( this ); -} - -// --------------------------------------------------------------------- - void SmartAssertBase::AbortNow() const { - CommandLineAssertPolicy::AbortNow( this ); + CerrAssertPolicy::AbortNow( this ); } // --------------------------------------------------------------------- @@ -383,15 +373,18 @@ void SmartAssertBase::HandleFailure() { m_handled = true; + if ( FixedProblem() ) + { + return; + } try { + CallOutput(); if ( Info_ == m_level ) { - CallOutput(); return; } - CallOutput(); if ( m_level == Fatal_ ) { AbortNow(); @@ -431,57 +424,42 @@ // --------------------------------------------------------------------- -void CommandLineAssertPolicy::Output( const SmartAssertBase * asserter ) +void CommonOutput( const SmartAssertBase * asserter, bool use_cerr ) { - cout << SmartAssertBase::GetName( asserter->m_level ) - << "! Assertion failed! " << asserter->m_expression << endl; + ::std::basic_ostream< char > & out = ( use_cerr ) ? ::std::cerr : ::std::cout; + out << SmartAssertBase::GetName( asserter->m_level ) + << "! Assertion failed! " << asserter->m_expression << endl; if ( nullptr != asserter->m_context ) { - cout << "\t"; - asserter->m_context->Output(); + out << "\t"; + asserter->m_context->Output( use_cerr ); for ( const AssertContext * p = asserter->m_context->m_next; ( p != nullptr ); p = p->m_next ) { - cout << " "; - p->Output(); + out << " "; + p->Output( use_cerr ); } - cout << endl; + out << endl; } if ( ( nullptr != asserter->m_message ) && ( '\0' != *asserter->m_message ) ) { - cout << "\t" << asserter->m_message << endl; + out << "\t" << asserter->m_message << endl; } for ( const AssertInfo * p = asserter->m_info; ( p != nullptr ); p = p->m_next ) { - p->Output(); + p->Output( use_cerr ); } } // --------------------------------------------------------------------- -void CommandLineAssertPolicy::Debugger( const SmartAssertBase * ) +SmartAssertBase::UserResponse CommonAskUser( const SmartAssertBase * asserter, bool use_cerr ) { -#if defined( _WIN32 ) || defined( __WIN32__ ) || defined( WIN32 ) - ::DebugBreak(); // Win32 + ::std::basic_ostream< char > & output = ( use_cerr ) ? ::std::cerr : ::std::cout; -#elif ( defined _MSC_VER ) || ( defined __BORLANDC__) || ( defined __MWERKS__ ) - __asm { int 3 }; - -#elif defined(__GNUC__) // GCC - __asm ("int $0x3"); - -#else - # error "Please supply instruction to DebugBreak (like 'int 3' on Intel processors)" -#endif -} - -// --------------------------------------------------------------------- - -SmartAssertBase::UserResponse CommandLineAssertPolicy::AskUser( const SmartAssertBase * asserter ) -{ const char * prompt = ( SmartAssertBase::Error_ == asserter->m_level ) ? "\tChoose option: (I)gnore This Time, Ignore (E)ach Time, (D)ebug, (A)bort " : "\tChoose option: (I)gnore This Time, Ignore (E)ach Time, (D)ebug "; - ::std::cout << prompt; + output << prompt; bool keep_asking = true; while ( keep_asking ) @@ -502,7 +480,7 @@ } if ( !isspace( ch ) && keep_asking ) // ignore spaces { - std::cout << prompt; + output << prompt; } } @@ -511,8 +489,48 @@ // --------------------------------------------------------------------- -void CommandLineAssertPolicy::AbortNow( const SmartAssertBase * ) +bool CoutAssertPolicy::FixedProblem( const SmartAssertBase * ) { + return false; +} + +// --------------------------------------------------------------------- + +void CoutAssertPolicy::Output( const SmartAssertBase * asserter ) +{ + CommonOutput( asserter, false ); +} + +// --------------------------------------------------------------------- + +void CoutAssertPolicy::Debugger( const SmartAssertBase * ) +{ +#if defined( _WIN32 ) || defined( __WIN32__ ) || defined( WIN32 ) + ::DebugBreak(); // Win32 + +#elif ( defined _MSC_VER ) || ( defined __BORLANDC__) || ( defined __MWERKS__ ) + __asm { int 3 }; + +#elif defined(__GNUC__) // GCC + __asm ("int $0x3"); + +#else + # error "Please supply instruction to DebugBreak (like 'int 3' on Intel processors)" +#endif +} + +// --------------------------------------------------------------------- + +SmartAssertBase::UserResponse CoutAssertPolicy::AskUser( const SmartAssertBase * asserter ) +{ + const SmartAssertBase::UserResponse reply = CommonAskUser( asserter, false ); + return reply; +} + +// --------------------------------------------------------------------- + +void CoutAssertPolicy::AbortNow( const SmartAssertBase * ) +{ // This might be a good time to call any cleanup services, // and to log any useful information to a file. abort(); @@ -520,6 +538,21 @@ // --------------------------------------------------------------------- +void CerrAssertPolicy::Output( const SmartAssertBase * asserter ) +{ + CommonOutput( asserter, true ); +} + +// --------------------------------------------------------------------- + +SmartAssertBase::UserResponse CerrAssertPolicy::AskUser( const SmartAssertBase * asserter ) +{ + const SmartAssertBase::UserResponse reply = CommonAskUser( asserter, true ); + return reply; +} + +// --------------------------------------------------------------------- + #if defined( _MSC_VER ) #pragma warning( pop ) #endif Modified: trunk/test/SmartAssert/SmartAssert.cbp =================================================================== (Binary files differ) Modified: trunk/test/SmartAssert/main.cpp =================================================================== --- trunk/test/SmartAssert/main.cpp 2013-06-24 06:10:50 UTC (rev 1190) +++ trunk/test/SmartAssert/main.cpp 2013-08-06 22:56:31 UTC (rev 1191) @@ -37,6 +37,9 @@ #include <iostream> +#include <cassert> + + // --------------------------------------------------------------------- class Bogus { }; @@ -138,6 +141,66 @@ // --------------------------------------------------------------------- +/** @class ListAssertInfoOnSameLine + This policy class demonstrates how to write and use your own policies. + It lists assert info descriptions on the same line as their values. It + assumes that if an AssertInfo type is a C-style string, then it must be + a description of the next AssertInfo value. It also puts a blank at the + start of the output to vertically separate the assertion info from any + previous output by the host program. + */ +class ListAssertInfoOnSameLine : public Loki::CerrAssertPolicy +{ +public: + /// Displays information about assertion to the user. + static void Output( const Loki::SmartAssertBase * asserter ); +}; + +// --------------------------------------------------------------------- + +void ListAssertInfoOnSameLine::Output( const ::Loki::SmartAssertBase * asserter ) +{ + assert( nullptr != asserter ); + + ::std::cerr << ::std::endl << ::Loki::SmartAssertBase::GetName( asserter->m_level ) + << "! Assertion failed! " << asserter->m_expression << ::std::endl; + if ( nullptr != asserter->m_context ) + { + ::std::cerr << "\t"; + asserter->m_context->Output( true ); + for ( const ::Loki::AssertContext * p = asserter->m_context->m_next; ( p != nullptr ); p = p->m_next ) + { + ::std::cerr << " "; + p->Output( true ); + } + ::std::cerr << ::std::endl; + } + if ( ( nullptr != asserter->m_message ) && ( '\0' != *asserter->m_message ) ) + { + ::std::cerr << "\t" << asserter->m_message << ::std::endl; + } + + const char * description = nullptr; + for ( const ::Loki::AssertInfo * p = asserter->m_info; ( p != nullptr ); p = p->m_next ) + { + if ( ( ::Loki::AssertInfo::CharPtr == p->m_type ) + && ( p->m_next != nullptr ) ) + { + description = p->m_value.m_p_char; + p = p->m_next; + } + else + { + description = ""; + } + ::std::cerr << "\t" << Loki::AssertInfo::GetName( p->m_type ) << ": " << description << " ("; + p->m_value.Output( p->m_type, true ); + ::std::cerr << ')' << ::std::endl; + } +} + +// --------------------------------------------------------------------- + int main( int argc, const char * argv[] ) { @@ -156,9 +219,24 @@ int a3 = 3; LOKI_SMART_ASSERT( 0 == argc ).Warn()( a1 )( a2 )( a3 )(); - // Show how to put names of variables into assertion info. - LOKI_SMART_ASSERT( 0 == argc ).Warn()( a1 )( "a1" )( a2 )( "a2" )( a3 )( "a3" )(); + const unsigned int counted = 57; + const char * name = "Darth Cuddles"; + const bool result = true; + // Show how to put variables names into assertion info. + LOKI_SMART_ASSERT( 0 == argc ).Warn()( counted )( "counted" )( name )( "name" )( result )( "result" )(); + // Same as before, but this shows how to use a policy to put variable names on the same line as their values. + LOKI_SMART_ASSERT_POLICIED( 0 == argc, ListAssertInfoOnSameLine ).Warn() + ( counted )( "counted" )( name )( "name" )( result )( "result" )(); + + // Same as before, but this shows how to use a policy to put variable descriptions on the same line as their values. + LOKI_SMART_ASSERT_POLICIED( 0 == argc, ListAssertInfoOnSameLine ).Warn() + ( counted )( "death toll" )( name )( "villain" )( result )( "Does evil lose?" )(); + + // Same as before, but this shows how to mix names/descriptions and unnamed variables in the same assertion output. + LOKI_SMART_ASSERT_POLICIED( 0 == argc, ListAssertInfoOnSameLine ).Warn()( a1 ) + ( counted )( "death toll" )( name )( "villain" )( a3 )( result )( "Does evil lose?" )( a2 )(); + test_data_types( argc, argv ); test_ignore( argc ); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2013-06-24 06:10:53
|
Revision: 1190 http://sourceforge.net/p/loki-lib/code/1190 Author: rich_sposato Date: 2013-06-24 06:10:50 +0000 (Mon, 24 Jun 2013) Log Message: ----------- Minor changes to remove compiler warnings. Modified Paths: -------------- trunk/include/loki/SmartAssert.hpp trunk/src/SmartAssert.cpp Modified: trunk/include/loki/SmartAssert.hpp =================================================================== --- trunk/include/loki/SmartAssert.hpp 2013-06-24 06:09:34 UTC (rev 1189) +++ trunk/include/loki/SmartAssert.hpp 2013-06-24 06:10:50 UTC (rev 1190) @@ -236,7 +236,7 @@ VoidPtr, Float, Double, - LongDouble, + LongDouble }; static const char * GetName( DataTypeTag tag ); Modified: trunk/src/SmartAssert.cpp =================================================================== --- trunk/src/SmartAssert.cpp 2013-06-24 06:09:34 UTC (rev 1189) +++ trunk/src/SmartAssert.cpp 2013-06-24 06:10:50 UTC (rev 1190) @@ -524,4 +524,4 @@ #pragma warning( pop ) #endif -}; // end namespace +} // end namespace This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2013-06-24 06:09:37
|
Revision: 1189 http://sourceforge.net/p/loki-lib/code/1189 Author: rich_sposato Date: 2013-06-24 06:09:34 +0000 (Mon, 24 Jun 2013) Log Message: ----------- Use std namespace for C string functions. Modified Paths: -------------- trunk/include/loki/SafeFormat.h trunk/src/SafeFormat.cpp Modified: trunk/include/loki/SafeFormat.h =================================================================== --- trunk/include/loki/SafeFormat.h 2013-06-24 06:08:05 UTC (rev 1188) +++ trunk/include/loki/SafeFormat.h 2013-06-24 06:09:34 UTC (rev 1189) @@ -35,7 +35,6 @@ #include <cstdio> #include <climits> -#include <string> #include <cstring> #include <stdexcept> #include <utility> @@ -254,7 +253,7 @@ result_ = -1; return *this; } - const size_t len = std::min(std::strlen(s), prec_); + const size_t len = std::min(::std::strlen(s), prec_); if (width_ > len) { if (LeftJustify()) { Write(s, s + len); @@ -309,7 +308,7 @@ SetAlternateForm(); // printed with '0x' in front isSigned = true; // that's what gcc does } - if (!strchr("cdiuoxX", formatChar)) { + if (!::std::strchr("cdiuoxX", formatChar)) { result_ = -1; return; } @@ -404,7 +403,7 @@ // enforce format string validity ReadLeaders(); // enforce format spec - if (!strchr(check_fmt_char, *format_)) { + if (!::std::strchr(check_fmt_char, *format_)) { result_ = -1; return; } @@ -434,7 +433,7 @@ result_ = -1; return; } - Write(resultBuf, resultBuf + strlen(resultBuf)); + Write(resultBuf, resultBuf + ::std::strlen(resultBuf)); Advance(); // output stuff to the next format directive } Modified: trunk/src/SafeFormat.cpp =================================================================== --- trunk/src/SafeFormat.cpp 2013-06-24 06:08:05 UTC (rev 1188) +++ trunk/src/SafeFormat.cpp 2013-06-24 06:09:34 UTC (rev 1189) @@ -132,7 +132,7 @@ } PrintfState<std::string&, char> SPrintf(std::string& s, const char* format) { - const size_t estimate = ::strlen( format ) + 128; + const size_t estimate = ::std::strlen( format ) + 128; s.reserve( estimate ); return PrintfState<std::string&, char>(s, format); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2013-06-24 06:08:08
|
Revision: 1188 http://sourceforge.net/p/loki-lib/code/1188 Author: rich_sposato Date: 2013-06-24 06:08:05 +0000 (Mon, 24 Jun 2013) Log Message: ----------- Changed cast style. Modified Paths: -------------- trunk/test/CheckReturn/main.cpp Modified: trunk/test/CheckReturn/main.cpp =================================================================== --- trunk/test/CheckReturn/main.cpp 2013-06-24 06:05:43 UTC (rev 1187) +++ trunk/test/CheckReturn/main.cpp 2013-06-24 06:08:05 UTC (rev 1188) @@ -136,7 +136,7 @@ BoolReturn checkBool = CheckRequired(); // and then deliberately ignores it before destructor runs. // Ignore any compiler warnings that says code does not check return value. - (bool)checkBool; + static_cast< bool >( checkBool ); cout << "Called CheckRequired, stored return value, and ignored it." << endl; } @@ -145,14 +145,14 @@ // This should not assert since caller deliberately chooses to not // check return value by casting to return value to correct type. // Ignore any compiler warnings that says code does not check return value. - (bool)CheckRequired(); + static_cast< bool >( CheckRequired() ); } { // This should not assert since caller deliberately chooses to not // check return value by casting to return value to correct type. // Ignore any compiler warnings that says code does not check return value. - (bool)CheckRequired( false ); + static_cast< bool >( CheckRequired( false ) ); cout << "Made a nested call to CheckRequired." << endl; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2013-06-24 06:05:45
|
Revision: 1187 http://sourceforge.net/p/loki-lib/code/1187 Author: rich_sposato Date: 2013-06-24 06:05:43 +0000 (Mon, 24 Jun 2013) Log Message: ----------- Updated to use new version of C++ standard. Modified Paths: -------------- trunk/Makefile.common Modified: trunk/Makefile.common =================================================================== --- trunk/Makefile.common 2013-06-24 05:13:49 UTC (rev 1186) +++ trunk/Makefile.common 2013-06-24 06:05:43 UTC (rev 1187) @@ -2,6 +2,6 @@ OS ?= $(shell uname -s) CXXWARNFLAGS := -Wall -Wold-style-cast -Wundef -Wsign-compare -Wconversion -Wpointer-arith -pedantic -CXXFLAGS := $(CXXWARNFLAGS) -g -O2 +CXXFLAGS := $(CXXWARNFLAGS) -g -O2 -std=c++0x prefix := /usr This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2013-06-24 05:13:52
|
Revision: 1186 http://sourceforge.net/p/loki-lib/code/1186 Author: rich_sposato Date: 2013-06-24 05:13:49 +0000 (Mon, 24 Jun 2013) Log Message: ----------- Changed unsigned int to uintptr_t. Patch #23. Modified Paths: -------------- trunk/test/LevelMutex/MultiThreadTests.cpp trunk/test/LevelMutex/Thing.cpp trunk/test/LevelMutex/Thing.hpp trunk/test/Lockable/main.cpp trunk/test/SafeFormat/main.cpp trunk/test/ThreadLocal/ThreadTests.cpp Modified: trunk/test/LevelMutex/MultiThreadTests.cpp =================================================================== --- trunk/test/LevelMutex/MultiThreadTests.cpp 2013-06-23 01:14:58 UTC (rev 1185) +++ trunk/test/LevelMutex/MultiThreadTests.cpp 2013-06-24 05:13:49 UTC (rev 1186) @@ -89,7 +89,7 @@ void * PrintSafeThread( void * p ) { - unsigned int value = reinterpret_cast< unsigned int >( p ); + uintptr_t value = reinterpret_cast< uintptr_t >( p ); volatile Thing & thing = Thing::GetIt(); try { @@ -119,7 +119,7 @@ void * PrintUnsafeThread( void * p ) { - unsigned int value = reinterpret_cast< unsigned int >( p ); + uintptr_t value = reinterpret_cast< uintptr_t >( p ); Thing & thing = const_cast< Thing & >( Thing::GetIt() ); try { @@ -147,7 +147,7 @@ // ---------------------------------------------------------------------------- -void OutputResults( unsigned int loop, unsigned int value, unsigned int result ) +void OutputResults( unsigned int loop, uintptr_t value, uintptr_t result ) { static volatile SleepMutex mutex( 2 ); static bool initialized = false; @@ -177,7 +177,7 @@ const unsigned int testCount = 8; unsigned int fails = 0; - const unsigned int value = reinterpret_cast< unsigned int >( p ); + const uintptr_t value = reinterpret_cast< uintptr_t >( p ); volatile Thing & thing = Thing::GetIt(); try { @@ -187,7 +187,7 @@ (void)locker; thing.SetValue( value ); ::GoToSleep( 3 ); - const unsigned int result = thing.GetValue(); + const uintptr_t result = thing.GetValue(); OutputResults( ii, value, result ); if ( result != value ) fails++; @@ -210,7 +210,7 @@ const unsigned int testCount = 8; unsigned int fails = 0; - const unsigned int value = reinterpret_cast< unsigned int >( p ); + const uintptr_t value = reinterpret_cast< uintptr_t >( p ); // cast away volatility so the mutex doesn't get used by volatile functions. Thing & thing = const_cast< Thing & >( Thing::GetIt() ); try @@ -219,7 +219,7 @@ { thing.SetValue( value ); ::GoToSleep( 3 ); - const unsigned int result = thing.GetValue(); + const uintptr_t result = thing.GetValue(); OutputResults( ii, value, result ); if ( result != value ) fails++; @@ -249,7 +249,7 @@ cout << "Doing thread-locked print test. This test should pass and not deadlock" << endl; cout << "Press <Enter> key to start test. "; cin.get( ender ); - for ( unsigned int ii = 0; ii < threadCount; ++ii ) + for ( uintptr_t ii = 0; ii < threadCount; ++ii ) { void * p = reinterpret_cast< void * >( ii ); pool.Start( PrintSafeThread, p ); @@ -262,7 +262,7 @@ cout << endl << "Doing thread-unsafe print test. This test may fail, but not deadlock." << endl; cout << "Press <Enter> key to start test. "; cin.get( ender ); - for ( unsigned int ii = 0; ii < threadCount; ++ii ) + for ( uintptr_t ii = 0; ii < threadCount; ++ii ) { void * p = reinterpret_cast< void * >( ii ); pool.Start( PrintUnsafeThread, p ); @@ -279,7 +279,7 @@ void * TryLockThread( void * p ) { - const unsigned int value = reinterpret_cast< unsigned int >( p ); + const uintptr_t value = reinterpret_cast< uintptr_t >( p ); volatile Thing & thing = Thing::GetIt(); volatile SleepMutex & mutex = thing.GetMutex(); assert( mutex.IsLockedByAnotherThread() ); @@ -297,7 +297,7 @@ result = mutex.Unlock(); assert( result == MutexErrors::Success ); } - const unsigned int gotValue = thing.GetValue(); + const uintptr_t gotValue = thing.GetValue(); assert( gotValue != value ); (void)gotValue; } @@ -313,7 +313,7 @@ cout << "Starting MultiThreadTryLockTest." << endl; char ender; - static const unsigned int threadCount = 3; + static const uintptr_t threadCount = 3; Thing::Init( 0 ); volatile Thing & thing = Thing::GetIt(); volatile SleepMutex & mutex = thing.GetMutex(); @@ -330,13 +330,13 @@ cout << endl << "Doing multi-threaded TryLock test. This test should not deadlock." << endl; cout << "Press <Enter> key to start test. "; cin.get( ender ); - for ( unsigned int ii = 0; ii < threadCount; ++ii ) + for ( uintptr_t ii = 0; ii < threadCount; ++ii ) { void * p = reinterpret_cast< void * >( ii ); pool.Start( TryLockThread, p ); } pool.JoinAll(); - const unsigned int value = thing.GetValue(); + const uintptr_t value = thing.GetValue(); assert( value == threadCount ); } @@ -368,7 +368,7 @@ cout << endl << "Doing thread-safe value test. This test should pass and not deadlock." << endl; cout << "Press <Enter> key to start test. "; cin.get( ender ); - for ( unsigned int ii = 0; ii < threadCount; ++ii ) + for ( uintptr_t ii = 0; ii < threadCount; ++ii ) { void * p = reinterpret_cast< void * >( ii ); pool.Start( ValueSafeThread, p ); @@ -401,7 +401,7 @@ bool RandomizeMutexOrder( LevelMutexInfo::MutexContainer & mutexes ) { - unsigned int count = mutexes.size(); + const size_t count = mutexes.size(); if ( count < 2 ) return false; @@ -409,7 +409,7 @@ for ( unsigned int ii = 0; ii < count; ++ii ) { volatile LevelMutexInfo * mutex = nullptr; - const unsigned int sizeNow = mutexes.size(); + const size_t sizeNow = mutexes.size(); if ( 1 < sizeNow ) { unsigned int index = ( ::rand() % sizeNow ); @@ -542,7 +542,7 @@ void * MultiLockSafeThread( void * p ) { - const unsigned int value = reinterpret_cast< unsigned int >( p ); + const uintptr_t value = reinterpret_cast< uintptr_t >( p ); LevelMutexInfo::MutexContainer mutexes( thingCount ); volatile Thing * thing = nullptr; unsigned int jj = 0; @@ -618,7 +618,7 @@ void * MultiLockUnsafeThread( void * p ) { - const unsigned int value = reinterpret_cast< unsigned int >( p ); + const uintptr_t value = reinterpret_cast< uintptr_t >( p ); Thing * thing = nullptr; unsigned int jj = 0; unsigned int tests = 0; @@ -683,7 +683,7 @@ char ender; Thing::MakePool( thingCount ); - const unsigned int threadCount = 8; + const uintptr_t threadCount = 8; TestResults::Create( threadCount ); { @@ -691,7 +691,7 @@ cout << endl << "Doing thread-safe multi-lock test. This test should pass and not deadlock." << endl; cout << "Press <Enter> key to start test. "; cin.get( ender ); - for ( unsigned int ii = 0; ii < threadCount; ++ii ) + for ( uintptr_t ii = 0; ii < threadCount; ++ii ) { void * p = reinterpret_cast< void * >( ii ); pool.Start( MultiLockSafeThread, p ); @@ -706,7 +706,7 @@ TestResults::GetIt()->Reset( threadCount ); cout << "Press <Enter> key to start test. "; cin.get( ender ); - for ( unsigned int ii = 0; ii < threadCount; ++ii ) + for ( uintptr_t ii = 0; ii < threadCount; ++ii ) { void * p = reinterpret_cast< void * >( ii ); pool.Start( MultiLockUnsafeThread, p ); @@ -725,7 +725,7 @@ void * MultiLockRandomSafeThread( void * p ) { - const unsigned int value = reinterpret_cast< unsigned int >( p ); + const uintptr_t value = reinterpret_cast< uintptr_t >( p ); unsigned int testCount = 0; unsigned int failCount = 0; volatile Thing * thing = nullptr; @@ -751,7 +751,7 @@ assert( nullptr != thing ); pool.push_back( thing ); } - const unsigned int poolCount = pool.size(); + const size_t poolCount = pool.size(); mutexes.clear(); for ( jj = 0; jj < poolCount; ++jj ) @@ -795,7 +795,7 @@ void * MultiLockRandomUnsafeThread( void * p ) { - const unsigned int value = reinterpret_cast< unsigned int >( p ); + const uintptr_t value = reinterpret_cast< uintptr_t >( p ); unsigned int testCount = 0; unsigned int failCount = 0; Thing * thing = nullptr; @@ -819,7 +819,7 @@ assert( nullptr != thing ); pool.push_back( thing ); } - const unsigned int poolCount = pool.size(); + const size_t poolCount = pool.size(); for ( jj = 0; jj < poolCount; ++jj ) { @@ -857,7 +857,7 @@ char ender; Thing::MakePool( thingCount ); - const unsigned int threadCount = 8; + const uintptr_t threadCount = 8; TestResults::Create( threadCount ); { @@ -865,7 +865,7 @@ cout << endl << "Doing thread-safe random multi-lock test. This test should pass and not deadlock." << endl; cout << "Press <Enter> key to start test. "; cin.get( ender ); - for ( unsigned int ii = 0; ii < threadCount; ++ii ) + for ( uintptr_t ii = 0; ii < threadCount; ++ii ) { void * p = reinterpret_cast< void * >( ii ); pool.Start( MultiLockRandomSafeThread, p ); @@ -880,7 +880,7 @@ TestResults::GetIt()->Reset( threadCount ); cout << "Press <Enter> key to start test. "; cin.get( ender ); - for ( unsigned int ii = 0; ii < threadCount; ++ii ) + for ( uintptr_t ii = 0; ii < threadCount; ++ii ) { void * p = reinterpret_cast< void * >( ii ); pool.Start( MultiLockRandomUnsafeThread, p ); @@ -900,7 +900,7 @@ void * SafeHierarchyTest( void * p ) { - const unsigned int value = reinterpret_cast< unsigned int >( p ); + const uintptr_t value = reinterpret_cast< uintptr_t >( p ); volatile LevelThing * thing = nullptr; unsigned int testCount = 0; unsigned int failCount = 0; @@ -949,7 +949,7 @@ void * UnsafeHierarchyTest( void * p ) { - const unsigned int value = reinterpret_cast< unsigned int >( p ); + const uintptr_t value = reinterpret_cast< uintptr_t >( p ); LevelThing * thing = nullptr; unsigned int testCount = 0; unsigned int failCount = 0; @@ -997,7 +997,7 @@ char ender; LevelThing::MakePool( thingCount ); - const unsigned int threadCount = 8; + const uintptr_t threadCount = 8; TestResults::Create( threadCount ); { @@ -1005,7 +1005,7 @@ cout << endl << "Doing thread-safe hierarchy test. This test should pass and not deadlock." << endl; cout << "Press <Enter> key to start test. "; cin.get( ender ); - for ( unsigned int ii = 0; ii < threadCount; ++ii ) + for ( uintptr_t ii = 0; ii < threadCount; ++ii ) { void * p = reinterpret_cast< void * >( ii ); pool.Start( SafeHierarchyTest, p ); @@ -1020,7 +1020,7 @@ cout << "Press <Enter> key to start test. "; cin.get( ender ); TestResults::GetIt()->Reset( threadCount ); - for ( unsigned int ii = 0; ii < threadCount; ++ii ) + for ( uintptr_t ii = 0; ii < threadCount; ++ii ) { void * p = reinterpret_cast< void * >( ii ); pool.Start( UnsafeHierarchyTest, p ); @@ -1040,7 +1040,7 @@ void * SafeHierarchyMultiLockTest( void * p ) { - const unsigned int value = reinterpret_cast< unsigned int >( p ); + const uintptr_t value = reinterpret_cast< uintptr_t >( p ); unsigned int testCount = 0; unsigned int failCount = 0; unsigned int totalTestCount = 0; @@ -1091,7 +1091,7 @@ void * UnsafeHierarchyMultiLockTest( void * p ) { - const unsigned int value = reinterpret_cast< unsigned int >( p ); + const uintptr_t value = reinterpret_cast< uintptr_t >( p ); unsigned int testCount = 0; unsigned int failCount = 0; unsigned int totalTestCount = 0; @@ -1137,7 +1137,7 @@ char ender; MultiLevelPool::MakePool( 10, thingCount ); - const unsigned int threadCount = 8; + const uintptr_t threadCount = 8; TestResults::Create( threadCount ); { @@ -1145,7 +1145,7 @@ cout << endl << "Doing thread-safe multilock hierarchy test. This test should pass and not deadlock." << endl; cout << "Press <Enter> key to start test. "; cin.get( ender ); - for ( unsigned int ii = 0; ii < threadCount; ++ii ) + for ( uintptr_t ii = 0; ii < threadCount; ++ii ) { void * p = reinterpret_cast< void * >( ii ); pool.Start( SafeHierarchyMultiLockTest, p ); @@ -1160,7 +1160,7 @@ cout << "Press <Enter> key to start test. "; cin.get( ender ); TestResults::GetIt()->Reset( threadCount ); - for ( unsigned int ii = 0; ii < threadCount; ++ii ) + for ( uintptr_t ii = 0; ii < threadCount; ++ii ) { void * p = reinterpret_cast< void * >( ii ); pool.Start( UnsafeHierarchyMultiLockTest, p ); Modified: trunk/test/LevelMutex/Thing.cpp =================================================================== --- trunk/test/LevelMutex/Thing.cpp 2013-06-23 01:14:58 UTC (rev 1185) +++ trunk/test/LevelMutex/Thing.cpp 2013-06-24 05:13:49 UTC (rev 1186) @@ -195,7 +195,7 @@ // ---------------------------------------------------------------------------- -void TestResults::SetResult( unsigned int threadIndex, unsigned int total, +void TestResults::SetResult( uintptr_t threadIndex, unsigned int total, unsigned int fails ) { assert( NULL != this ); @@ -361,7 +361,7 @@ // ---------------------------------------------------------------------------- -void Thing::Print( unsigned int value, unsigned int index, unsigned int startSize ) const volatile +void Thing::Print( uintptr_t value, unsigned int index, unsigned int startSize ) const volatile { assert( NULL != this ); MutexLocker locker( m_mutex ); @@ -374,7 +374,7 @@ // ---------------------------------------------------------------------------- -void Thing::Print( unsigned int value, unsigned int index, unsigned int startSize ) const +void Thing::Print( uintptr_t value, unsigned int index, unsigned int startSize ) const { assert( NULL != this ); switch ( startSize ) @@ -402,7 +402,7 @@ // ---------------------------------------------------------------------------- -void Thing::SetValue( unsigned int value ) volatile +void Thing::SetValue( uintptr_t value ) volatile { assert( NULL != this ); SingleThingLocker pSafeThis( *this, m_mutex ); @@ -506,7 +506,7 @@ // ---------------------------------------------------------------------------- -void LevelThing::SetValue( unsigned int value ) volatile +void LevelThing::SetValue( uintptr_t value ) volatile { assert( NULL != this ); MutexLocker locker( m_mutex, !m_mutex.IsLockedByCurrentThread() ); @@ -522,7 +522,7 @@ // ---------------------------------------------------------------------------- -void LevelThing::SetValue( unsigned int value ) +void LevelThing::SetValue( uintptr_t value ) { assert( NULL != this ); m_value = value; @@ -536,7 +536,7 @@ // ---------------------------------------------------------------------------- -bool LevelThing::DoValuesMatch( unsigned int value ) const volatile +bool LevelThing::DoValuesMatch( uintptr_t value ) const volatile { assert( NULL != this ); { @@ -555,7 +555,7 @@ // ---------------------------------------------------------------------------- -bool LevelThing::DoValuesMatch( unsigned int value ) const +bool LevelThing::DoValuesMatch( uintptr_t value ) const { assert( NULL != this ); if ( m_value != value ) @@ -592,7 +592,7 @@ // ---------------------------------------------------------------------------- -void SomeThing::SetValue( unsigned int value ) volatile +void SomeThing::SetValue( uintptr_t value ) volatile { assert( NULL != this ); SomeThingLocker pSafeThis( *this, m_mutex ); @@ -707,7 +707,7 @@ // ---------------------------------------------------------------------------- void CheckForMatchingValues( unsigned int & failCount, unsigned int & testCount, - unsigned int value, const SomeThingPool & pool ) + uintptr_t value, const SomeThingPool & pool ) { const unsigned int count = pool.size(); for ( unsigned int ii = 0; ii < count; ++ii ) @@ -723,7 +723,7 @@ // ---------------------------------------------------------------------------- void CheckForMatchingValues( unsigned int & failCount, unsigned int & testCount, - unsigned int value, const SomeThingPool & pool, bool locked ) + uintptr_t value, const SomeThingPool & pool, bool locked ) { if ( !locked ) { Modified: trunk/test/LevelMutex/Thing.hpp =================================================================== --- trunk/test/LevelMutex/Thing.hpp 2013-06-23 01:14:58 UTC (rev 1185) +++ trunk/test/LevelMutex/Thing.hpp 2013-06-24 05:13:49 UTC (rev 1186) @@ -27,7 +27,17 @@ #include <vector> +#if !defined(_MSC_VER) + #if defined(__sparc__) + #include <inttypes.h> + #else + #include <stdint.h> + #endif +#else + typedef unsigned int uintptr_t; +#endif + // ---------------------------------------------------------------------------- void GoToSleep( unsigned int milliSeconds ); @@ -89,7 +99,7 @@ void Reset( unsigned int threadCount ); - void SetResult( unsigned int threadIndex, unsigned int total, + void SetResult( uintptr_t threadIndex, unsigned int total, unsigned int fails ); void OutputResults( void ); @@ -142,17 +152,17 @@ static void DestroyPool( void ); - void Print( unsigned int value, unsigned int index, unsigned int startSize ) const volatile; + void Print( uintptr_t value, unsigned int index, unsigned int startSize ) const volatile; - void Print( unsigned int value, unsigned int index, unsigned int startSize ) const; + void Print( uintptr_t value, unsigned int index, unsigned int startSize ) const; - unsigned int GetValue( void ) const volatile { return m_value; } + uintptr_t GetValue( void ) const volatile { return m_value; } - unsigned int GetValue( void ) const { return m_value; } + uintptr_t GetValue( void ) const { return m_value; } - void SetValue( unsigned int value ) volatile; + void SetValue( uintptr_t value ) volatile; - void SetValue( unsigned int value ) { m_value = value; } + void SetValue( uintptr_t value ) { m_value = value; } inline volatile SleepMutex & GetMutex( void ) volatile { return m_mutex; } @@ -175,7 +185,7 @@ static TestResults s_results; mutable volatile SleepMutex m_mutex; - unsigned int m_value; + uintptr_t m_value; }; typedef ::std::vector< Thing * > UnsafeThingPool; @@ -219,17 +229,17 @@ void UnlockHierarchy( void ) volatile; - void SetValue( unsigned int value ) volatile; + void SetValue( uintptr_t value ) volatile; - void SetValue( unsigned int value ); + void SetValue( uintptr_t value ); - inline unsigned int GetValue( void ) const volatile { return m_value; } + inline uintptr_t GetValue( void ) const volatile { return m_value; } - inline unsigned int GetValue( void ) const { return m_value; } + inline uintptr_t GetValue( void ) const { return m_value; } - bool DoValuesMatch( unsigned int value ) const volatile; + bool DoValuesMatch( uintptr_t value ) const volatile; - bool DoValuesMatch( unsigned int value ) const; + bool DoValuesMatch( uintptr_t value ) const; inline volatile ::Loki::LevelMutexInfo & GetMutex( void ) volatile { return m_mutex; } @@ -251,7 +261,7 @@ mutable volatile SleepMutex m_mutex; const unsigned int m_place; - unsigned int m_value; + uintptr_t m_value; }; // ---------------------------------------------------------------------------- @@ -266,13 +276,13 @@ inline unsigned int GetLevel( void ) const volatile { return m_level; } - void SetValue( unsigned int value ) volatile; + void SetValue( uintptr_t value ) volatile; - void SetValue( unsigned int value ); + void SetValue( uintptr_t value ); - inline unsigned int GetValue( void ) const volatile { return m_value; } + inline uintptr_t GetValue( void ) const volatile { return m_value; } - inline unsigned int GetValue( void ) const { return m_value; } + inline uintptr_t GetValue( void ) const { return m_value; } inline volatile ::Loki::LevelMutexInfo & GetMutex( void ) volatile { return m_mutex; } @@ -287,7 +297,7 @@ mutable volatile SleepMutex m_mutex; const unsigned int m_place; const unsigned int m_level; - unsigned int m_value; + uintptr_t m_value; }; typedef ::std::vector< volatile SomeThing * > SomeThingPool; @@ -346,10 +356,10 @@ // ---------------------------------------------------------------------------- void CheckForMatchingValues( unsigned int & failCount, unsigned int & testCount, - unsigned int value, const SomeThingPool & pool ); + uintptr_t value, const SomeThingPool & pool ); void CheckForMatchingValues( unsigned int & failCount, unsigned int & testCount, - unsigned int value, const SomeThingPool & pool, bool locked ); + uintptr_t value, const SomeThingPool & pool, bool locked ); void MakePool( SomeThingPool & pool ); Modified: trunk/test/Lockable/main.cpp =================================================================== --- trunk/test/Lockable/main.cpp 2013-06-23 01:14:58 UTC (rev 1185) +++ trunk/test/Lockable/main.cpp 2013-06-24 05:13:49 UTC (rev 1186) @@ -36,6 +36,17 @@ #include "ThreadPool.hpp" +#if !defined(_MSC_VER) + #if defined(__sparc__) + #include <inttypes.h> + #else + #include <stdint.h> + #endif +#else + typedef unsigned int uintptr_t; +#endif + + using namespace std; static unsigned int g = 0; @@ -58,25 +69,25 @@ typedef ::Loki::ObjectLevelLockable< LockableObject > BaseClass; - explicit LockableObject( unsigned int index ) : + explicit LockableObject( uintptr_t index ) : BaseClass(), m_index( index ), m_value( ObjectCount ) {} ~LockableObject( void ) {} - unsigned int GetIndex( void ) const { return m_index; } + uintptr_t GetIndex( void ) const { return m_index; } - unsigned int GetValue( void ) const { return m_value; } + uintptr_t GetValue( void ) const { return m_value; } - void SetValue( unsigned int value ) { m_value = value; } + void SetValue( uintptr_t value ) { m_value = value; } void DoSomething( void ); - void Print( unsigned int threadIndex ); + void Print( uintptr_t threadIndex ); private: - const unsigned int m_index; - unsigned int m_value; + const uintptr_t m_index; + uintptr_t m_value; }; @@ -90,7 +101,7 @@ // ---------------------------------------------------------------------------- -void LockableObject::Print( unsigned int threadIndex ) +void LockableObject::Print( uintptr_t threadIndex ) { assert( NULL != this ); const char * result = ( threadIndex != m_value ) ? "Mismatch!" : ""; @@ -126,7 +137,7 @@ void * RunObjectTest( void * p ) { - const unsigned int threadIndex = reinterpret_cast< unsigned int >( p ); + const uintptr_t threadIndex = reinterpret_cast< uintptr_t >( p ); assert( threadIndex < ThreadCount ); unsigned int failCount = 0; @@ -140,7 +151,7 @@ object->DoSomething(); object->Print( threadIndex ); object->DoSomething(); - const unsigned int value = object->GetValue(); + const uintptr_t value = object->GetValue(); if ( value != threadIndex ) ++failCount; } @@ -192,23 +203,23 @@ typedef ::Loki::ClassLevelLockable< LockableClass > BaseClass; - explicit LockableClass( unsigned int index ) : BaseClass(), m_index( index ) {} + explicit LockableClass( uintptr_t index ) : BaseClass(), m_index( index ) {} ~LockableClass( void ) {} - unsigned int GetIndex( void ) const { return m_index; } + uintptr_t GetIndex( void ) const { return m_index; } - void Print( unsigned int threadIndex ); + void Print( uintptr_t threadIndex ); private: /// Assignment operator is not implemented. LockableClass & operator = ( const LockableClass & ); - const unsigned int m_index; + const uintptr_t m_index; }; // ---------------------------------------------------------------------------- -void LockableClass::Print( unsigned int threadIndex ) +void LockableClass::Print( uintptr_t threadIndex ) { assert( NULL != this ); DO; ::Loki::Printf( "%u: %u: -----\n" )( m_index )( threadIndex ); @@ -245,7 +256,7 @@ void * RunClassTest( void * p ) { - const unsigned int threadIndex = reinterpret_cast< unsigned int >( p ); + const uintptr_t threadIndex = reinterpret_cast< uintptr_t >( p ); assert( threadIndex < ThreadCount ); for ( unsigned int ii = 0; ii < ClassCount; ++ii ) Modified: trunk/test/SafeFormat/main.cpp =================================================================== --- trunk/test/SafeFormat/main.cpp 2013-06-23 01:14:58 UTC (rev 1185) +++ trunk/test/SafeFormat/main.cpp 2013-06-24 05:13:49 UTC (rev 1186) @@ -23,6 +23,17 @@ #include "ThreadPool.hpp" +#if !defined(_MSC_VER) + #if defined(__sparc__) + #include <inttypes.h> + #else + #include <stdint.h> + #endif +#else + typedef unsigned int uintptr_t; +#endif + + #if defined(_MSC_VER) #if _MSC_VER >= 1400 #define sprintf sprintf_s @@ -367,7 +378,7 @@ void * DoLokiFPrintfLoop( void * p ) { - const unsigned int threadIndex = reinterpret_cast< unsigned int >( p ); + const uintptr_t threadIndex = reinterpret_cast< uintptr_t >( p ); for ( unsigned int loop = 0; loop < 10; ++loop ) { @@ -381,7 +392,7 @@ void * DoLokiPrintfLoop( void * p ) { - const unsigned int threadIndex = reinterpret_cast< unsigned int >( p ); + const uintptr_t threadIndex = reinterpret_cast< uintptr_t >( p ); for ( unsigned int loop = 0; loop < 10; ++loop ) { @@ -395,7 +406,7 @@ void * DoStdOutLoop( void * p ) { - const unsigned int threadIndex = reinterpret_cast< unsigned int >( p ); + const uintptr_t threadIndex = reinterpret_cast< uintptr_t >( p ); for ( unsigned int loop = 0; loop < 10; ++loop ) { @@ -409,7 +420,7 @@ void * DoCoutLoop( void * p ) { - const unsigned int threadIndex = reinterpret_cast< unsigned int >( p ); + const uintptr_t threadIndex = reinterpret_cast< uintptr_t >( p ); for ( unsigned int loop = 0; loop < 10; ++loop ) { Modified: trunk/test/ThreadLocal/ThreadTests.cpp =================================================================== --- trunk/test/ThreadLocal/ThreadTests.cpp 2013-06-23 01:14:58 UTC (rev 1185) +++ trunk/test/ThreadLocal/ThreadTests.cpp 2013-06-24 05:13:49 UTC (rev 1186) @@ -37,11 +37,22 @@ #include <cassert> +#if !defined(_MSC_VER) + #if defined(__sparc__) + #include <inttypes.h> + #else + #include <stdint.h> + #endif +#else + typedef unsigned int uintptr_t; +#endif + + // ---------------------------------------------------------------------------- -typedef ::std::vector< unsigned int > IntVector; +typedef ::std::vector< uintptr_t > IntVector; -static LOKI_THREAD_LOCAL unsigned int StandaloneStaticValue = 0; +static LOKI_THREAD_LOCAL uintptr_t StandaloneStaticValue = 0; static const unsigned int ThreadCount = 4; @@ -49,7 +60,7 @@ IntVector & GetIntVector( void ) { - unsigned int v = 0; + uintptr_t v = 0; static IntVector addresses( ThreadCount, v ); return addresses; } @@ -59,7 +70,7 @@ void * AddToIntVector( void * p ) { assert( 0 == StandaloneStaticValue ); - const unsigned int ii = reinterpret_cast< unsigned int >( p ); + const uintptr_t ii = reinterpret_cast< uintptr_t >( p ); assert( 0 < ii ); assert( ii < ThreadCount + 1 ); StandaloneStaticValue = ii; @@ -86,10 +97,10 @@ IntVector & v = GetIntVector(); for ( unsigned int i1 = 0; i1 < ThreadCount - 1; ++i1 ) { - const unsigned int v1 = v[ i1 ]; + const uintptr_t v1 = v[ i1 ]; for ( unsigned int i2 = i1 + 1; i2 < ThreadCount; ++i2 ) { - const unsigned int v2 = v[ i2 ]; + const uintptr_t v2 = v[ i2 ]; if ( v1 == v2 ) { allDifferent = false; @@ -106,9 +117,9 @@ // ---------------------------------------------------------------------------- -unsigned int & GetFunctionThreadLocalValue( void ) +uintptr_t & GetFunctionThreadLocalValue( void ) { - static LOKI_THREAD_LOCAL unsigned int FunctionStaticValue = 0; + static LOKI_THREAD_LOCAL uintptr_t FunctionStaticValue = 0; return FunctionStaticValue; } @@ -116,9 +127,9 @@ void * ChangeFunctionStaticValue( void * p ) { - unsigned int & thatValue = GetFunctionThreadLocalValue(); + uintptr_t & thatValue = GetFunctionThreadLocalValue(); assert( 0 == thatValue ); - const unsigned int ii = reinterpret_cast< unsigned int >( p ); + const uintptr_t ii = reinterpret_cast< uintptr_t >( p ); assert( 0 < ii ); assert( ii < ThreadCount + 1 ); thatValue = ii + ThreadCount; @@ -151,10 +162,10 @@ bool allDifferent = true; for ( unsigned int i1 = 0; i1 < ThreadCount - 1; ++i1 ) { - const unsigned int v1 = v[ i1 ]; + const uintptr_t v1 = v[ i1 ]; for ( unsigned int i2 = i1 + 1; i2 < ThreadCount; ++i2 ) { - const unsigned int v2 = v[ i2 ]; + const uintptr_t v2 = v[ i2 ]; if ( v1 == v2 ) { allDifferent = false; @@ -175,24 +186,24 @@ { public: - static inline void SetValue( unsigned int value ) { ClassThreadLocal = value; } + static inline void SetValue( uintptr_t value ) { ClassThreadLocal = value; } - static inline unsigned int GetValue( void ) { return ClassThreadLocal; } + static inline uintptr_t GetValue( void ) { return ClassThreadLocal; } private: - static LOKI_THREAD_LOCAL unsigned int ClassThreadLocal; + static LOKI_THREAD_LOCAL uintptr_t ClassThreadLocal; }; -LOKI_THREAD_LOCAL unsigned int ThreadAware::ClassThreadLocal = 0; +LOKI_THREAD_LOCAL uintptr_t ThreadAware::ClassThreadLocal = 0; // ---------------------------------------------------------------------------- void * ChangeClassStaticValue( void * p ) { assert( ThreadAware::GetValue() == 0 ); - const unsigned int ii = reinterpret_cast< unsigned int >( p ); + const uintptr_t ii = reinterpret_cast< uintptr_t >( p ); assert( 0 < ii ); assert( ii < ThreadCount + 1 ); ThreadAware::SetValue( ii + 2 * ThreadCount ); @@ -225,10 +236,10 @@ bool allDifferent = true; for ( unsigned int i1 = 0; i1 < ThreadCount - 1; ++i1 ) { - const unsigned int v1 = v[ i1 ]; + const uintptr_t v1 = v[ i1 ]; for ( unsigned int i2 = i1 + 1; i2 < ThreadCount; ++i2 ) { - const unsigned int v2 = v[ i2 ]; + const uintptr_t v2 = v[ i2 ]; if ( v1 == v2 ) { allDifferent = false; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2013-06-23 01:15:00
|
Revision: 1185 http://sourceforge.net/p/loki-lib/code/1185 Author: rich_sposato Date: 2013-06-23 01:14:58 +0000 (Sun, 23 Jun 2013) Log Message: ----------- Changed types to remove compiler warning. Modified Paths: -------------- trunk/test/LevelMutex/ThreadPool.cpp trunk/test/LevelMutex/ThreadPool.hpp trunk/test/SmallObj/timer.h Modified: trunk/test/LevelMutex/ThreadPool.cpp =================================================================== --- trunk/test/LevelMutex/ThreadPool.cpp 2013-06-19 02:23:00 UTC (rev 1184) +++ trunk/test/LevelMutex/ThreadPool.cpp 2013-06-23 01:14:58 UTC (rev 1185) @@ -177,7 +177,7 @@ if ( threadCount <= countNow ) return threadCount; - const unsigned int totalCount = pThis->m_threads.size(); + const size_t totalCount = pThis->m_threads.size(); const unsigned int howManyToAdd = threadCount - countNow; if ( pThis->m_threads.capacity() <= howManyToAdd ) pThis->m_threads.reserve( totalCount + howManyToAdd ); @@ -200,12 +200,12 @@ // ---------------------------------------------------------------------------- -unsigned int ThreadPool::GetCount( void ) const volatile +size_t ThreadPool::GetCount( void ) const volatile { assert( IsValid() ); LOKI_DEBUG_CODE( Checker checker( this ); (void)checker; ) ThreadPool * pThis = const_cast< ThreadPool * >( this ); - const unsigned int count = pThis->m_threads.size(); + const size_t count = pThis->m_threads.size(); return count; } Modified: trunk/test/LevelMutex/ThreadPool.hpp =================================================================== --- trunk/test/LevelMutex/ThreadPool.hpp 2013-06-19 02:23:00 UTC (rev 1184) +++ trunk/test/LevelMutex/ThreadPool.hpp 2013-06-23 01:14:58 UTC (rev 1185) @@ -139,7 +139,7 @@ void JoinAll( void ) const volatile; - unsigned int GetCount( void ) const volatile; + size_t GetCount( void ) const volatile; unsigned int GetCount( Thread::Status status ) const volatile; Modified: trunk/test/SmallObj/timer.h =================================================================== --- trunk/test/SmallObj/timer.h 2013-06-19 02:23:00 UTC (rev 1184) +++ trunk/test/SmallObj/timer.h 2013-06-23 01:14:58 UTC (rev 1185) @@ -38,8 +38,8 @@ { t1 = clock(); } - - int t() + + clock_t t() { return t1-t0; } @@ -67,8 +67,8 @@ std::cout << s << "\tseconds: " << sec(t) << "\trelative time: " << rel(t) << "%\tspeed-up factor: " << speedup(t) << "" << std::endl; } private: - int t0; - int t1; + clock_t t0; + clock_t t1; }; #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2013-06-19 02:23:07
|
Revision: 1184 http://sourceforge.net/p/loki-lib/code/1184 Author: rich_sposato Date: 2013-06-19 02:23:00 +0000 (Wed, 19 Jun 2013) Log Message: ----------- Added SmartAssert to Loki. Modified Paths: -------------- trunk/Loki.cbp trunk/Loki.sln trunk/Loki.workspace trunk/include/loki/ScopeGuard.h Added Paths: ----------- trunk/include/loki/Concatenate.h trunk/include/loki/SmartAssert.hpp trunk/src/SmartAssert.cpp trunk/test/SmartAssert/ trunk/test/SmartAssert/SmartAssert.cbp trunk/test/SmartAssert/SmartAssert.vcxproj trunk/test/SmartAssert/main.cpp Modified: trunk/Loki.cbp =================================================================== --- trunk/Loki.cbp 2012-04-03 05:46:56 UTC (rev 1183) +++ trunk/Loki.cbp 2013-06-19 02:23:00 UTC (rev 1184) @@ -6,9 +6,9 @@ <Option compiler="cygwin" /> <Build> <Target title="Debug_GCC"> - <Option output="./lib/GCC/Loki_D.a" prefix_auto="0" extension_auto="0" /> + <Option output=".\lib\GCC\Loki_D.a" prefix_auto="0" extension_auto="0" /> <Option working_dir="" /> - <Option object_output="obj/Debug_GCC/" /> + <Option object_output="obj\Debug_GCC\" /> <Option type="2" /> <Option compiler="gcc" /> <Option createDefFile="1" /> @@ -17,27 +17,27 @@ <Add option="-W" /> <Add option="-DDEBUG" /> <Add directory="." /> - <Add directory="./include" /> - <Add directory="./include/loki" /> + <Add directory=".\include" /> + <Add directory=".\include\loki" /> </Compiler> </Target> <Target title="Release_GCC"> - <Option output="./lib/GCC/Loki.a" prefix_auto="0" extension_auto="0" /> + <Option output=".\lib\GCC\Loki.a" prefix_auto="0" extension_auto="0" /> <Option working_dir="" /> - <Option object_output="obj/Release_GCC/" /> + <Option object_output="obj\Release_GCC\" /> <Option type="2" /> <Option compiler="gcc" /> <Option createDefFile="1" /> <Compiler> <Add option="-W" /> - <Add directory="./include/loki" /> - <Add directory="./include" /> + <Add directory=".\include\loki" /> + <Add directory=".\include" /> </Compiler> </Target> <Target title="Debug_Cygwin"> - <Option output="./lib/Cygwin/Loki_D.a" prefix_auto="0" extension_auto="0" /> + <Option output=".\lib\Cygwin\Loki_D.a" prefix_auto="0" extension_auto="0" /> <Option working_dir="" /> - <Option object_output="obj/Debug_Cygwin/" /> + <Option object_output="obj\Debug_Cygwin\" /> <Option type="2" /> <Option compiler="cygwin" /> <Option createDefFile="1" /> @@ -45,88 +45,90 @@ <Add option="-W" /> <Add option="-g" /> <Add directory="." /> - <Add directory="./include" /> - <Add directory="./include/loki" /> + <Add directory=".\include" /> + <Add directory=".\include\loki" /> </Compiler> </Target> <Target title="Release_Cygwin"> - <Option output="./lib/Cygwin/Loki.a" prefix_auto="0" extension_auto="0" /> + <Option output=".\lib\Cygwin\Loki.a" prefix_auto="0" extension_auto="0" /> <Option working_dir="" /> - <Option object_output="obj/Release_Cygwin/" /> + <Option object_output="obj\Release_Cygwin\" /> <Option type="2" /> <Option compiler="cygwin" /> <Option createDefFile="1" /> <Compiler> <Add option="-W" /> - <Add directory="./include/loki" /> - <Add directory="./include" /> + <Add directory=".\include\loki" /> + <Add directory=".\include" /> </Compiler> </Target> </Build> - <Unit filename="include/loki/AbstractFactory.h" /> - <Unit filename="include/loki/Allocator.h" /> - <Unit filename="include/loki/AssocVector.h" /> - <Unit filename="include/loki/CachedFactory.h" /> - <Unit filename="include/loki/CheckReturn.h" /> - <Unit filename="include/loki/Checker.h" /> - <Unit filename="include/loki/ConstPolicy.h" /> - <Unit filename="include/loki/DataGenerators.h" /> - <Unit filename="include/loki/EmptyType.h" /> - <Unit filename="include/loki/Factory.h" /> - <Unit filename="include/loki/Function.h" /> - <Unit filename="include/loki/Functor.h" /> - <Unit filename="include/loki/HierarchyGenerators.h" /> - <Unit filename="include/loki/Key.h" /> - <Unit filename="include/loki/LevelMutex.h" /> - <Unit filename="include/loki/LockingPtr.h" /> - <Unit filename="include/loki/LokiExport.h" /> - <Unit filename="include/loki/LokiTypeInfo.h" /> - <Unit filename="include/loki/MultiMethods.h" /> - <Unit filename="include/loki/NullType.h" /> - <Unit filename="include/loki/OrderedStatic.h" /> - <Unit filename="include/loki/Pimpl.h" /> - <Unit filename="include/loki/RefToValue.h" /> - <Unit filename="include/loki/Register.h" /> - <Unit filename="include/loki/SPCachedFactory.h" /> - <Unit filename="include/loki/SafeBits.h" /> - <Unit filename="include/loki/SafeFormat.h" /> - <Unit filename="include/loki/ScopeGuard.h" /> - <Unit filename="include/loki/Sequence.h" /> - <Unit filename="include/loki/Singleton.h" /> - <Unit filename="include/loki/SmallObj.h" /> - <Unit filename="include/loki/SmartPtr.h" /> - <Unit filename="include/loki/StrongPtr.h" /> - <Unit filename="include/loki/ThreadLocal.h" /> - <Unit filename="include/loki/Threads.h" /> - <Unit filename="include/loki/Tuple.h" /> - <Unit filename="include/loki/TypeManip.h" /> - <Unit filename="include/loki/TypeTraits.h" /> - <Unit filename="include/loki/Typelist.h" /> - <Unit filename="include/loki/TypelistMacros.h" /> - <Unit filename="include/loki/Visitor.h" /> - <Unit filename="include/loki/flex/allocatorstringstorage.h" /> - <Unit filename="include/loki/flex/cowstringopt.h" /> - <Unit filename="include/loki/flex/flex_string.h" /> - <Unit filename="include/loki/flex/flex_string_details.h" /> - <Unit filename="include/loki/flex/flex_string_shell.h" /> - <Unit filename="include/loki/flex/simplestringstorage.h" /> - <Unit filename="include/loki/flex/smallstringopt.h" /> - <Unit filename="include/loki/flex/vectorstringstorage.h" /> - <Unit filename="include/loki/static_check.h" /> - <Unit filename="include/loki/yasli/platform.h" /> - <Unit filename="include/loki/yasli/random.h" /> - <Unit filename="include/loki/yasli/yasli_fill_iterator.h" /> - <Unit filename="include/loki/yasli/yasli_memory.h" /> - <Unit filename="include/loki/yasli/yasli_protocols.h" /> - <Unit filename="include/loki/yasli/yasli_traits.h" /> - <Unit filename="include/loki/yasli/yasli_vector.h" /> - <Unit filename="src/LevelMutex.cpp" /> - <Unit filename="src/OrderedStatic.cpp" /> - <Unit filename="src/SafeFormat.cpp" /> - <Unit filename="src/Singleton.cpp" /> - <Unit filename="src/SmallObj.cpp" /> - <Unit filename="src/SmartPtr.cpp" /> - <Unit filename="src/StrongPtr.cpp" /> + <Unit filename="include\loki\AbstractFactory.h" /> + <Unit filename="include\loki\Allocator.h" /> + <Unit filename="include\loki\AssocVector.h" /> + <Unit filename="include\loki\CachedFactory.h" /> + <Unit filename="include\loki\CheckReturn.h" /> + <Unit filename="include\loki\Checker.h" /> + <Unit filename="include\loki\ConstPolicy.h" /> + <Unit filename="include\loki\DataGenerators.h" /> + <Unit filename="include\loki\EmptyType.h" /> + <Unit filename="include\loki\Factory.h" /> + <Unit filename="include\loki\Function.h" /> + <Unit filename="include\loki\Functor.h" /> + <Unit filename="include\loki\HierarchyGenerators.h" /> + <Unit filename="include\loki\Key.h" /> + <Unit filename="include\loki\LevelMutex.h" /> + <Unit filename="include\loki\LockingPtr.h" /> + <Unit filename="include\loki\LokiExport.h" /> + <Unit filename="include\loki\LokiTypeInfo.h" /> + <Unit filename="include\loki\MultiMethods.h" /> + <Unit filename="include\loki\NullType.h" /> + <Unit filename="include\loki\OrderedStatic.h" /> + <Unit filename="include\loki\Pimpl.h" /> + <Unit filename="include\loki\RefToValue.h" /> + <Unit filename="include\loki\Register.h" /> + <Unit filename="include\loki\SPCachedFactory.h" /> + <Unit filename="include\loki\SafeBits.h" /> + <Unit filename="include\loki\SafeFormat.h" /> + <Unit filename="include\loki\ScopeGuard.h" /> + <Unit filename="include\loki\Sequence.h" /> + <Unit filename="include\loki\Singleton.h" /> + <Unit filename="include\loki\SmallObj.h" /> + <Unit filename="include\loki\SmartAssert.hpp" /> + <Unit filename="include\loki\SmartPtr.h" /> + <Unit filename="include\loki\StrongPtr.h" /> + <Unit filename="include\loki\ThreadLocal.h" /> + <Unit filename="include\loki\Threads.h" /> + <Unit filename="include\loki\Tuple.h" /> + <Unit filename="include\loki\TypeManip.h" /> + <Unit filename="include\loki\TypeTraits.h" /> + <Unit filename="include\loki\Typelist.h" /> + <Unit filename="include\loki\TypelistMacros.h" /> + <Unit filename="include\loki\Visitor.h" /> + <Unit filename="include\loki\flex\allocatorstringstorage.h" /> + <Unit filename="include\loki\flex\cowstringopt.h" /> + <Unit filename="include\loki\flex\flex_string.h" /> + <Unit filename="include\loki\flex\flex_string_details.h" /> + <Unit filename="include\loki\flex\flex_string_shell.h" /> + <Unit filename="include\loki\flex\simplestringstorage.h" /> + <Unit filename="include\loki\flex\smallstringopt.h" /> + <Unit filename="include\loki\flex\vectorstringstorage.h" /> + <Unit filename="include\loki\static_check.h" /> + <Unit filename="include\loki\yasli\platform.h" /> + <Unit filename="include\loki\yasli\random.h" /> + <Unit filename="include\loki\yasli\yasli_fill_iterator.h" /> + <Unit filename="include\loki\yasli\yasli_memory.h" /> + <Unit filename="include\loki\yasli\yasli_protocols.h" /> + <Unit filename="include\loki\yasli\yasli_traits.h" /> + <Unit filename="include\loki\yasli\yasli_vector.h" /> + <Unit filename="src\LevelMutex.cpp" /> + <Unit filename="src\OrderedStatic.cpp" /> + <Unit filename="src\SafeFormat.cpp" /> + <Unit filename="src\Singleton.cpp" /> + <Unit filename="src\SmallObj.cpp" /> + <Unit filename="src\SmartAssert.cpp" /> + <Unit filename="src\SmartPtr.cpp" /> + <Unit filename="src\StrongPtr.cpp" /> <Extensions> <code_completion /> <envvars /> Modified: trunk/Loki.sln =================================================================== --- trunk/Loki.sln 2012-04-03 05:46:56 UTC (rev 1183) +++ trunk/Loki.sln 2013-06-19 02:23:00 UTC (rev 1184) @@ -1,7 +1,5 @@ Microsoft Visual Studio Solution File, Format Version 11.00 # Visual C++ Express 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Loki", "src\library.vcxproj", "{CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Factory", "test\Factory\Factory.vcxproj", "{925D5863-2F77-41B7-96F1-CC814762C40F}" ProjectSection(ProjectDependencies) = postProject {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} = {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} @@ -23,6 +21,9 @@ EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ScopeGuard", "test\ScopeGuard\ScopeGuard.vcxproj", "{D5E7BAC2-A961-4ECC-ADA4-82D7510952BA}" + ProjectSection(ProjectDependencies) = postProject + {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} = {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Singleton", "test\Singleton\Singleton.vcxproj", "{9F489E5D-9F29-4235-A9D4-79B5BA4EC48D}" ProjectSection(ProjectDependencies) = postProject @@ -30,8 +31,14 @@ EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Visitor", "test\Visitor\Visitor.vcxproj", "{0A696379-10A2-43FB-A26C-B42456FCF657}" + ProjectSection(ProjectDependencies) = postProject + {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} = {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "flex_string", "test\flex_string\flex_string.vcxproj", "{2022B9AD-34CA-4FDA-80C2-42805FABE65B}" + ProjectSection(ProjectDependencies) = postProject + {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} = {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SmallObjCompare", "test\SmallObj\SmallObjCompare.vcxproj", "{0A98B714-818C-4DD3-A07C-BDD16399F362}" ProjectSection(ProjectDependencies) = postProject @@ -44,8 +51,14 @@ EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DeletableSingleton", "test\DeletableSingleton\DeletableSingleton.vcxproj", "{B87B3522-7DAA-400D-A47D-A74B9B8B3552}" + ProjectSection(ProjectDependencies) = postProject + {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} = {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DefaultAlloc", "test\SmallObj\DefaultAlloc.vcxproj", "{D490B134-B794-42CF-8AF8-9FDA524B9D3B}" + ProjectSection(ProjectDependencies) = postProject + {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} = {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SmartPtr", "test\SmartPtr\SmartPtr.vcxproj", "{D7AB4FEF-E7AF-443D-93A5-37F323F2042D}" ProjectSection(ProjectDependencies) = postProject @@ -58,6 +71,9 @@ EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Pimpl", "test\Pimpl\Pimpl.vcxproj", "{21D2B291-80F4-476C-A643-B8A7034DF95F}" + ProjectSection(ProjectDependencies) = postProject + {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} = {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LockingPtr", "test\LockingPtr\LockingPtr.vcxproj", "{25766C3F-C0D8-429F-A212-5FA3537B3E1C}" ProjectSection(ProjectDependencies) = postProject @@ -65,10 +81,19 @@ EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Function", "test\Function\Function.vcxproj", "{2DE18D06-0F3A-4C6D-AF2B-40E074B3C3DC}" + ProjectSection(ProjectDependencies) = postProject + {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} = {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CachedFactory", "test\CachedFactory\CachedFactory.vcxproj", "{8D186AB4-E544-42D6-B192-1AE2C946875E}" + ProjectSection(ProjectDependencies) = postProject + {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} = {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CheckReturn", "test\CheckReturn\CheckReturn.vcxproj", "{C0826A05-9143-4545-B5DE-811C188CB54E}" + ProjectSection(ProjectDependencies) = postProject + {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} = {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Checker", "test\Checker\Checker.vcxproj", "{B1C04D81-E666-466A-A394-A3E74C830692}" ProjectSection(ProjectDependencies) = postProject @@ -81,8 +106,14 @@ EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SafeBits", "test\SafeBits\SafeBits.vcxproj", "{ECD7ED50-B99D-44BE-BA38-E17D6110C3E5}" + ProjectSection(ProjectDependencies) = postProject + {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} = {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AssocVector", "test\AssocVector\AssocVector.vcxproj", "{0605A820-D075-48AC-ABB6-D3FF05D5CD1F}" + ProjectSection(ProjectDependencies) = postProject + {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} = {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ThreadLocal", "test\ThreadLocal\ThreadLocal.vcxproj", "{27CB0BB1-1754-46AB-A8C6-697D1B9B9C41}" EndProject @@ -91,23 +122,24 @@ {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} = {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AtomicThread", "test\AtomicThread\AtomicThread.vcxproj", "{BF3C905E-512C-4E64-B737-A6C5B3A18C7E}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Register", "test\Register\Register.vcxproj", "{873CFBF9-0D03-42D5-B2F9-A4C95A15EBCD}" ProjectSection(ProjectDependencies) = postProject {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} = {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "library", "src\Library.vcxproj", "{CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SmartAssert", "test\SmartAssert\SmartAssert.vcxproj", "{DA7BBAE5-1C1A-4B5E-ABF1-2B5090DB2988}" + ProjectSection(ProjectDependencies) = postProject + {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} = {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0}.Debug|Win32.ActiveCfg = Debug|Win32 - {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0}.Debug|Win32.Build.0 = Debug|Win32 - {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0}.Release|Win32.ActiveCfg = Release|Win32 - {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0}.Release|Win32.Build.0 = Release|Win32 {925D5863-2F77-41B7-96F1-CC814762C40F}.Debug|Win32.ActiveCfg = Debug|Win32 {925D5863-2F77-41B7-96F1-CC814762C40F}.Debug|Win32.Build.0 = Debug|Win32 {925D5863-2F77-41B7-96F1-CC814762C40F}.Release|Win32.ActiveCfg = Release|Win32 @@ -208,14 +240,18 @@ {22A34627-1480-4180-A8B6-4C05E77E27F8}.Debug|Win32.Build.0 = Debug|Win32 {22A34627-1480-4180-A8B6-4C05E77E27F8}.Release|Win32.ActiveCfg = Release|Win32 {22A34627-1480-4180-A8B6-4C05E77E27F8}.Release|Win32.Build.0 = Release|Win32 - {BF3C905E-512C-4E64-B737-A6C5B3A18C7E}.Debug|Win32.ActiveCfg = Debug|Win32 - {BF3C905E-512C-4E64-B737-A6C5B3A18C7E}.Debug|Win32.Build.0 = Debug|Win32 - {BF3C905E-512C-4E64-B737-A6C5B3A18C7E}.Release|Win32.ActiveCfg = Release|Win32 - {BF3C905E-512C-4E64-B737-A6C5B3A18C7E}.Release|Win32.Build.0 = Release|Win32 {873CFBF9-0D03-42D5-B2F9-A4C95A15EBCD}.Debug|Win32.ActiveCfg = Debug|Win32 {873CFBF9-0D03-42D5-B2F9-A4C95A15EBCD}.Debug|Win32.Build.0 = Debug|Win32 {873CFBF9-0D03-42D5-B2F9-A4C95A15EBCD}.Release|Win32.ActiveCfg = Release|Win32 {873CFBF9-0D03-42D5-B2F9-A4C95A15EBCD}.Release|Win32.Build.0 = Release|Win32 + {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0}.Debug|Win32.ActiveCfg = Debug|Win32 + {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0}.Debug|Win32.Build.0 = Debug|Win32 + {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0}.Release|Win32.ActiveCfg = Release|Win32 + {CBDB8E7A-4286-4AE3-A190-BA33D7C53FF0}.Release|Win32.Build.0 = Release|Win32 + {DA7BBAE5-1C1A-4B5E-ABF1-2B5090DB2988}.Debug|Win32.ActiveCfg = Debug|Win32 + {DA7BBAE5-1C1A-4B5E-ABF1-2B5090DB2988}.Debug|Win32.Build.0 = Debug|Win32 + {DA7BBAE5-1C1A-4B5E-ABF1-2B5090DB2988}.Release|Win32.ActiveCfg = Release|Win32 + {DA7BBAE5-1C1A-4B5E-ABF1-2B5090DB2988}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE Modified: trunk/Loki.workspace =================================================================== --- trunk/Loki.workspace 2012-04-03 05:46:56 UTC (rev 1183) +++ trunk/Loki.workspace 2013-06-19 02:23:00 UTC (rev 1184) @@ -14,7 +14,7 @@ <Project filename="test/Factory/Factory.cbp" /> <Project filename="test/flex_string/flex_string.cbp" /> <Project filename="test/Function/Function.cbp" /> - <Project filename="test/LevelMutex/LevelMutex.cbp" active="1"> + <Project filename="test/LevelMutex/LevelMutex.cbp"> <Depends filename="Loki.cbp" /> </Project> <Project filename="test/Lockable/Lockable.cbp"> @@ -50,5 +50,8 @@ <Project filename="test/SmallObj/SmallObjSingleton.cbp"> <Depends filename="Loki.cbp" /> </Project> + <Project filename="test/SmartAssert/SmartAssert.cbp" active="1"> + <Depends filename="Loki.cbp" /> + </Project> </Workspace> </CodeBlocks_workspace_file> Added: trunk/include/loki/Concatenate.h =================================================================== --- trunk/include/loki/Concatenate.h (rev 0) +++ trunk/include/loki/Concatenate.h 2013-06-19 02:23:00 UTC (rev 1184) @@ -0,0 +1,38 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2013 by Rich Sposato +// Code covered by the MIT License +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +//////////////////////////////////////////////////////////////////////////////// + +#ifndef LOKI_MACRO_CONCATENATE_INC_ +#define LOKI_MACRO_CONCATENATE_INC_ + +// $Id$ + +/** @note This header file provides a common definition of macros used to + concatenate names or numbers together into a single name or number. + */ + +#define LOKI_CONCATENATE_DIRECT(s1, s2) s1##s2 +#define LOKI_CONCATENATE(s1, s2) LOKI_CONCATENATE_DIRECT(s1, s2) + + +#endif Property changes on: trunk/include/loki/Concatenate.h ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Modified: trunk/include/loki/ScopeGuard.h =================================================================== --- trunk/include/loki/ScopeGuard.h 2012-04-03 05:46:56 UTC (rev 1183) +++ trunk/include/loki/ScopeGuard.h 2013-06-19 02:23:00 UTC (rev 1184) @@ -31,7 +31,9 @@ #include <exception> // needed for calls to uncaught_exception. #include <loki/RefToValue.h> +#include <loki/Concatenate.h> + /// \defgroup ExceptionGroup Exception-safe code namespace Loki @@ -699,8 +701,6 @@ } // namespace Loki -#define LOKI_CONCATENATE_DIRECT(s1, s2) s1##s2 -#define LOKI_CONCATENATE(s1, s2) LOKI_CONCATENATE_DIRECT(s1, s2) #define LOKI_ANONYMOUS_VARIABLE(str) LOKI_CONCATENATE(str, __LINE__) #define LOKI_ON_BLOCK_EXIT ::Loki::ScopeGuard LOKI_ANONYMOUS_VARIABLE(scopeGuard) = ::Loki::MakeGuard Added: trunk/include/loki/SmartAssert.hpp =================================================================== --- trunk/include/loki/SmartAssert.hpp (rev 0) +++ trunk/include/loki/SmartAssert.hpp 2013-06-19 02:23:00 UTC (rev 1184) @@ -0,0 +1,666 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2013 by Rich Sposato +// Code covered by the MIT License +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +//////////////////////////////////////////////////////////////////////////////// + + +#ifndef LOKI_SMART_ASSERT_HPP_INCLUDED +#define LOKI_SMART_ASSERT_HPP_INCLUDED + + +#include <loki/Concatenate.h> + +#if defined ( DEBUG ) || defined( DEBUG_ ) || defined( _DEBUG ) + #define LOKI_SMART_ASSERT_DEBUG +#endif + +#if defined( _MSC_VER ) + #pragma warning( push ) + #pragma warning( disable : 4514 ) + #pragma warning( disable : 4711 ) +#endif + +#if !defined( nullptr ) + #define LOKI_DEFINED_NULLPTR + #define nullptr 0 +#endif + + +namespace Loki +{ + +// --------------------------------------------------------------------- + +/** + @par SmartAssert Versus Dumb Assertions + Loki's SmartAssert provides features traditional assertions don't. + - Add a meaningful message to each assertion. + - Output values of variables when assertions fail. + - Different severity levels per assertion. + - Allows program to do something besides abort when assertions fail. + - Can ask user how to respond to assertions instead of just failing. + - Customizable output. + - Customizable way to ask user for response. + - Customizable way to start debugger. + - Allows program to do cleanup before dying. + + @par How to Use SmartAssert in 5 Minutes + The simplest way to use Loki's SmartAssert is to follow these steps. This is + the simplest way to use SmartAssert, and it gives you the same (or similar) + behaviors as assert. + - Add this line to your file: #include <loki/SmartAssert.hpp> + - Replace "assert( condition );" with "LOKI_SMART_ASSERT( condition );" + - Make sure you define one of these macros: DEBUG, _DEBUG, or DEBUG_. + - Compile and run your program. + + @par Adding Messages to your Assertions. + SmartAssert can output simple C-style strings as messages when an assertion + fails. Each assertion may have only one message. If you add more than one, + then only the right-most message is sent to output. To add a simple message + to your assertions, use the .Msg() function. + @code + LOKI_SMART_ASSERT( cond ).Msg( "Something is rotten in the state of Denmark." ); + @endcode + + @par Adding Variables to Your Assertions. + You can make SmartAssert output the values of variables by adding each + variable within a pair of parantheses. It will output them in the same order + they were added. You may chain as many variables to the assertion, but you + may only place fundamental types in the assertion. You can put them in any + order, but SmartAssert will store and output them in the reverse order in + which you add them. (i.e. Leftmost variables get outputted last, and + rightmost ones get outputted first.) Storing them in reverse order makes an + efficiency gain of O(n) over O(n*n). + @code + LOKI_SMART_ASSERT( cond )( a )( b ); + LOKI_SMART_ASSERT( cond )( a )( e )( c )( b )( d ); + @endcode + + SmartAssert won't know the purpose of those variables; only their type and + value. You can make SmartAssert output the names of the variables by using + the "stringify" preprocessor operator. This causes SmartAssert to create a + separate storage for the name and the variable itself. + @code + LOKI_SMART_ASSERT( cond )( a )( "a" )( b )( "b" ); + LOKI_SMART_ASSERT( cond )( a )( "a" )( e )( "e" )( b )( "b" ); + @endcode + + @par Setting the Severity Level + Assertions treat all error conditions as an excuse to commit suicide. That + one-size-fits-all solution seems overly drastic for minor errors. At least + SmartAssert gives the developer more detailed output to help understand why + the program died. + + SmartAssert provides multiple severity levels so developers have more options + besides seeing their programs die. The basic options are to start a debugger, + ignore the assertion that time, ignore it as long as the program runs, or + stop the program. The four severity levels and their effects are: + - Info: Just output the assertion info and continue on. + - Warn: Ask user to either ignore now, ignore always, or start debugger. + - Error: Same as above, but also give user option to abort program. + - Fatal: Program always ends when assertion fails and never asks user. + + SmartAssert's default severity level is Fatal so you can use it as a drop-in + replacement for assert and still get the same behavior. + + Here are some example calls to set the severity level. As you can see, the + calls may occur in any order within the assertion. + @code + LOKI_SMART_ASSERT( cond )( a )( b ).Info(); + LOKI_SMART_ASSERT( cond ).Warn()( a )( b ); + LOKI_SMART_ASSERT( cond )( a ).Error().( b ); + LOKI_SMART_ASSERT( cond ).Fatal().Msg( "Goodbye cruel world!" ); + LOKI_SMART_ASSERT( cond )( d ); // No severity level implies Fatal! + @endcode + + You could specify more than one severity level, but only the rightmost call + matters. In this example, Info() is further to the right so it overrides the + Fatal() call. + @code + LOKI_SMART_ASSERT( cond ).Fatal()( a )( b ).Info(); + @endcode + + @par User Intervention. + Since SmartAssert's default behaviors mimic assert, it normally doesn't ask + the user how to respond to an assertion failure. SmartAssert asks the user + only if the developer puts a call to operator() at the end of the assertion. + There is no need to ask the user to intervene if the severity level is Info. + If you write a policy class to either ask the user or call the debugger, you + should always add the call to operator(). + @code + LOKI_SMART_ASSERT( cond ).Warn()( a )(); // Asks user to intervene. + LOKI_SMART_ASSERT( cond ).Warn()( a ); // Does not ask user. + @endcode + + @par Write Your Own Policy. + Many parts of Loki were implemented using policy-based software design, and + SmartAssert follows that tradition. SmartAssert has a default policy that + mimics the behaviors of assert. If you want to make your own policy class, + write that class to have the same function signatures as + CommandLineAssertPolicy, and use the LOKI_SMART_ASSERT_POLICIED macro instead + of LOKI_SMART_ASSERT. + + @par Potential Policies + - To call a special debugger rather than the default one. + - To send output to a log file instead of to cout. + - To create a popup dialog box to ask the user. + - To attempt last moment cleanup before the program dies. + + @code + class MyPolicy + { + static void Output( const SmartAssertBase * asserter ); + static void Debugger( const SmartAssertBase * asserter ); + static SmartAssertBase::UserResponse AskUser( const SmartAssertBase * asserter ); + static void AbortNow( const SmartAssertBase * asserter ); + }; + LOKI_SMART_ASSERT_POLICIED( cond, MyPolicy ); + @endcode + + @par Thread Safety. + Each SmartAssert object is declared locally within a function, so it is only + accessible by the thread executing it. However, each SmartAssert makes its + own static boolean flag for whether to ignore its future failures. That + boolean flag is not thread_local, so telling SmartAssert to ignore it each + time applies to all threads. SmartAssert relies on a policy class, so it is + only as thread-safe as the functions in its policy class. + + @par Exception Safety. + SmartAssert wraps calls to the policy class within try-catch blocks. If an + exception occurs for Info or Warning level conditions, SmartAssert stops + processing the assertion and allows the calling function to continue. If an + exception occurs when processing an Error or Fatal assertion, SmartAssert + will abort immediately. + + @par Memory Usage. + SmartAssert does not allocate any memory or other resources, but functions + within policy classes might. + + @par Run-Time Efficiency. + No function call or operation within SmartAssert takes more than O(n) steps, + where n is the number of variables passed into SmartAssert. Most actions + complete in constant time. Functions in policy classes may not have the same + low run-time efficiency. +*/ + +// --------------------------------------------------------------------- + +/** @class AssertInfo Stores extra info user wants to pass into assertion. + This class has one constructor for each primitive data type so developers + can pass any primitive variable into the assert. + */ +class AssertInfo +{ +public: + + /** @enum DataTypeTag One tag for each primitive data type, plus a + few for pointers to char data types. + */ + enum DataTypeTag + { + Unknown = 0, + Boolean, + JustChar, + SignedChar, + UnsignedChar, + SignedShort, + UnsignedShort, + JustInt, + SignedInt, + UnsignedInt, + Long, + UnsignedLong, + LongInt, + UnsignedLongInt, + CharPtr, + SignedCharPtr, + UnsignedCharPtr, + VoidPtr, + Float, + Double, + LongDouble, + }; + + static const char * GetName( DataTypeTag tag ); + + /// @union DataValue Can be configured as any primitive data type. + union DataValue + { + bool m_bool; + char m_char; + signed char m_s_char; + unsigned char m_u_char; + signed short int m_s_short; + unsigned short int m_u_short; + int m_int; + unsigned int m_u_int; + long m_long; + unsigned long m_u_long; + signed long long int m_s_long_int; + unsigned long long int m_u_long_int; + const char * m_p_char; + const signed char * m_p_s_char; + const unsigned char * m_p_u_char; + const void * m_p_v; + float m_float; + double m_double; + long double m_l_double; + + DataValue() : m_bool( true ) {} + DataValue( const bool v ) : m_bool( v ) {} + DataValue( const char v ) : m_char( v ) {} + DataValue( const signed char v ) : m_s_char( v ) {} + DataValue( const unsigned char v ) : m_u_char( v ) {} + DataValue( const signed short int v ) : m_s_short( v ) {} + DataValue( const unsigned short int v ) : m_u_short( v ) {} + DataValue( const int v ) : m_int( v ) {} + DataValue( const unsigned int v ) : m_u_int( v ) {} + DataValue( const long v ) : m_long( v ) {} + DataValue( const unsigned long v ) : m_u_long( v ) {} + DataValue( const long long int v ) : m_s_long_int( v ) {} + DataValue( const unsigned long long int v ) : m_u_long_int( v ) {} + DataValue( const char * v ) : m_p_char( v ) {} + DataValue( const signed char * v ) : m_p_s_char( v ) {} + DataValue( const unsigned char * v ) : m_p_u_char( v ) {} + DataValue( const void * v ) : m_p_v( v ) {} + DataValue( const float v ) : m_float( v ) {} + DataValue( const double v ) : m_double( v ) {} + DataValue( const long double v ) : m_l_double( v ) {} + + void Output( DataTypeTag type ) const; + }; + + AssertInfo() : m_type( Unknown ), m_value(), m_next( nullptr ) {} + AssertInfo( bool v ) : m_type( Boolean ), m_value( v ), m_next( nullptr ) {} + AssertInfo( char v ) : m_type( JustChar ), m_value( v ), m_next( nullptr ) {} + AssertInfo( signed char v ) : m_type( SignedChar ), m_value( v ), m_next( nullptr ) {} + AssertInfo( unsigned char v ) : m_type( UnsignedChar ), m_value( v ), m_next( nullptr ) {} + AssertInfo( signed short v ) : m_type( SignedShort ), m_value( v ), m_next( nullptr ) {} + AssertInfo( unsigned short v ) : m_type( UnsignedShort ), m_value( v ), m_next( nullptr ) {} + AssertInfo( signed int v ) : m_type( SignedInt ), m_value( v ), m_next( nullptr ) {} + AssertInfo( unsigned int v ) : m_type( UnsignedInt ), m_value( v ), m_next( nullptr ) {} + AssertInfo( long v ) : m_type( Long ), m_value( v ), m_next( nullptr ) {} + AssertInfo( unsigned long v ) : m_type( UnsignedLong ), m_value( v ), m_next( nullptr ) {} + AssertInfo( long long int v ) : m_type( LongInt ), m_value( v ), m_next( nullptr ) {} + AssertInfo( unsigned long long int v ) : m_type( UnsignedLongInt ), m_value( v ), m_next( nullptr ) {} + AssertInfo( const char * v ) : m_type( CharPtr ), m_value( v ), m_next( nullptr ) {} + AssertInfo( const signed char * v ) : m_type( SignedCharPtr ), m_value( v ), m_next( nullptr ) {} + AssertInfo( const unsigned char * v ) : m_type( UnsignedCharPtr ), m_value( v ), m_next( nullptr ) {} + AssertInfo( const void * v ) : m_type( VoidPtr ), m_value( v ), m_next( nullptr ) {} + AssertInfo( float v ) : m_type( Float ), m_value( v ), m_next( nullptr ) {} + AssertInfo( double v ) : m_type( Double ), m_value( v ), m_next( nullptr ) {} + AssertInfo( long double v ) : m_type( LongDouble ), m_value( v ), m_next( nullptr ) {} + + /// Function provides default output action. + void Output() const; + + DataTypeTag m_type; ///< What type of data this stores. + DataValue m_value; ///< Value of that data. + mutable const AssertInfo * m_next; ///< Pointer to next piece of info, if any. +}; + +// --------------------------------------------------------------------- + +/** @class AssertContext Stores info about file, line, and function + where assertion occurred. Only two or three of these per SmartAssert. + + @note This class is optimized for storing info about the assertion's + location, not for storing general values. Use AssertInfo for storing + values of arbitary primitive types. + */ +class AssertContext +{ +public: + + /// Constructs context for source code line within file. + AssertContext( const char * description, unsigned int line ); + + /// Constructs context for source code filename or function name. + AssertContext( const char * description, const char * value ); + + /// Function provides default output action. + void Output() const; + + unsigned int m_line; ///< Line number within file. + const char * m_value; ///< Pointer to either filename or function name. + const char * m_description; ///< C-style string for describing piece of context. + mutable const AssertContext * m_next; ///< Pointer to next piece of context, if any. +}; + +// --------------------------------------------------------------------- + +class SmartAssertBase +{ +public: + + enum SeverityLevel + { + Info_, ///< Just warn user and do nothing else. (same as Warning and Ignore-Each-Time) + Warn_, ///< Give user options: (Ignore Once, Ignore Always, Debug) + Error_, ///< Give user options: (Ignore Once, Ignore Always, Debug, Abort) + Fatal_ ///< Always abort on failure. User gets no option to choose otherwise. + }; + + /// @enum Possible replies by the user when asked what to do about assertion. + enum UserResponse + { + /// Program continues as if assertion never happened, and asks + /// user what to do when assertion occurs again. + IgnoreThisTime = 'I', + /// Program continues executing, and never checks assertion for + /// the rest of the program's execution. If the program ends and + /// restarts, SmartAssert will check it again. + IgnoreEachTime = 'E', + /// Start the debugger at the place where the assertion failed. + DebugNow = 'D', + /// End the program now. + AbortProgram = 'A' + }; + + /// Gets one word description of severity level. + static const char * GetName( SeverityLevel level ); + + /// These three C-style strings contain descriptions used for assertion contexts. + static const char * const FileDesc; + static const char * const LineDesc; + static const char * const FunctionDesc; + + mutable const AssertContext * m_context; /// Linked-list of contexts of where assertion occurred. + mutable const AssertInfo * m_info; ///< Linked-list of values provided for output purposes. + SeverityLevel m_level; ///< How bad is this assertion? + bool * m_ignore; ///< Pointer to ignore-always flag. + const char * m_expression; ///< Pointer to C-style string of failed assertion expression. + const char * m_message; ///< Simple message made by developer. + bool m_handled; ///< True if this assertion was handled before destructor. + +protected: + + /// Default constructor is used for release builds. It ignores assertions. + SmartAssertBase(); + + /** This constructor gets used in debug builds. + @param ignore Pointer to boolean flag to ignore this assertion each time. + @param expression C-style string showing failed assertion. + */ + SmartAssertBase( bool * ignore, const char * expression ); + + /// Destructor handles assertion only when if not handled earlier. + virtual ~SmartAssertBase(); + + /// Called by derived class to add context information. + SmartAssertBase & AddContext( const AssertContext & info ); + + /// Called by derived class to add values used to display info about assertion. + SmartAssertBase & AddInfo( const AssertInfo & info ); + + /// Called to handle assertion failure. + void HandleFailure(); + + /// Default implementation of code to output information about assertion. + virtual void CallOutput() const; + + /// Default implementation of code to call debugger. + virtual void CallDebugger() const; + + /// Default implementation of code to ask user what to do. + virtual UserResponse AskUser() const; + + /// Default implementation of code to abort program. + virtual void AbortNow() const; + + /// Ignore-always flag used by assertions created in release builds. + static bool s_alwaysIgnore; +}; + +// --------------------------------------------------------------------- + +/** @class CommandLineAssertPolicy Default policy for command line programs. + Developers can implement their own policies to handle assertions by making a + class with the same function signatures as this class. If you write your own + policy class, you should also use the LOKI_SMART_ASSERT_POLICIED macro, and + not the LOKI_SMART_ASSERT macro. +*/ +class CommandLineAssertPolicy +{ +public: + + /// Displays information about assertion to the user. + static void Output( const SmartAssertBase * asserter ); + + /// Asks user how to handle assertion. + static SmartAssertBase::UserResponse AskUser( const SmartAssertBase * asserter ); + + /// Calls debugger. + static void Debugger( const SmartAssertBase * asserter ); + + /// This call should end the program. + static void AbortNow( const SmartAssertBase * asserter ); + +}; + +// --------------------------------------------------------------------- + +/** @class class SmartAssert + */ +template< class AssertPolicy > +class SmartAssert : public SmartAssertBase +{ +public: + + /// Default constructor used for when assertion passes. Should get optimized away. + SmartAssert() : SmartAssertBase() {} + + /// Constructor used when assertion fails. + SmartAssert( bool * ignore, const char * expression ) + : SmartAssertBase( ignore, expression ) {} + + /// Destructor is trivial. + virtual ~SmartAssert() {} + + /// Provides simple hard-coded C-style string message for output. + SmartAssert & Msg( const char * message ) { m_message = message; return *this; } + + SmartAssert & Info() { m_level = SmartAssertBase::Info_; return *this; } + SmartAssert & Warn() { m_level = SmartAssertBase::Warn_; return *this; } + SmartAssert & Error() { m_level = SmartAssertBase::Error_; return *this; } + SmartAssert & Fatal() { m_level = SmartAssertBase::Fatal_; return *this; } + + /// Called to do non-default actions when assertion fails. + void operator ()() { HandleFailure(); } + + /// Adds one piece of information to assertion, generally a variable or result of function call. + SmartAssert & operator ()( const AssertInfo & info ) + { + return static_cast< SmartAssert & >( AddInfo( info ) ); + } + + /// Called to add one piece of context to assertion, such as filename, line, or function name. + SmartAssert & Add( const AssertContext & info ) + { + return static_cast< SmartAssert & >( AddContext( info ) ); + } + +private: + + virtual void CallOutput() const + { + AssertPolicy::Output( dynamic_cast< const SmartAssertBase * >( this ) ); + } + + virtual void CallDebugger() const + { + AssertPolicy::Debugger( dynamic_cast< const SmartAssertBase * >( this ) ); + } + + virtual SmartAssertBase::UserResponse AskUser() const + { + return AssertPolicy::AskUser( dynamic_cast< const SmartAssertBase * >( this ) ); + } + + virtual void AbortNow() const + { + AssertPolicy::AbortNow( dynamic_cast< const SmartAssertBase * >( this ) ); + } + +}; + +// --------------------------------------------------------------------- + +} // namespace Loki + + +/// These lines let Loki put filename and line into AssertContext. +// note: using 'const char LOKI_SMART_ASSERT_FILE[] = __FILE__' +// does not work, since __FILE__ = "SmartAssert.hpp" +#define LOKI_SMART_ASSERT_FILE __FILE__ +#define LOKI_USE_NUMBER_FOR_UNIQUE_NAME __LINE__ + + +/** These lines determine if Loki can get the function name into AssertContext. + They also declare the macro used for creating unique names for SmartAssert + classes and variables. + */ +#define LOKI_SMART_ASSERT_FUNCTION_EXISTS + +#if defined(__GNUC__) || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) + # define LOKI_SMART_ASSERT_FUNCTION __PRETTY_FUNCTION__ + # undef LOKI_USE_NUMBER_FOR_UNIQUE_NAME + # define LOKI_USE_NUMBER_FOR_UNIQUE_NAME __COUNTER__ + +#elif defined(__FUNCSIG__) + # define LOKI_SMART_ASSERT_FUNCTION __FUNCSIG__ + +#elif defined(__BORLANDC__) && (__BORLANDC__ >= 0x550) + # define LOKI_SMART_ASSERT_FUNCTION __FUNC__ + +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901) + # define LOKI_SMART_ASSERT_FUNCTION __func__ + +#elif (defined __MSC_VER) && (__MSC_VER >= 1300) + # define LOKI_SMART_ASSERT_FUNCTION __FUNCDNAME__ + # undef LOKI_USE_NUMBER_FOR_UNIQUE_NAME + # define LOKI_USE_NUMBER_FOR_UNIQUE_NAME __COUNTER__ + +#elif defined(__IBMCPP__) && (__IBMCPP__ <= 500) + # define LOKI_SMART_ASSERT_FUNCTION __FUNCTION__ + +#elif (defined __HP_aCC) && (__HP_aCC <= 33300) + # define LOKI_SMART_ASSERT_FUNCTION __FUNCTION__ + +#else + # undef LOKI_SMART_ASSERT_FUNCTION_EXISTS +#endif + +#define LOKI_MAKE_UNIQUE_NAME( str ) LOKI_CONCATENATE( str, LOKI_USE_NUMBER_FOR_UNIQUE_NAME ) +#define LOKI_SMART_ASSERT_IGNORE_NAME LOKI_MAKE_UNIQUE_NAME( smartAssert_ignore_ ) +#define LOKI_SMART_ASSERT_CLASS_NAME LOKI_MAKE_UNIQUE_NAME( SmartAssert_ ) +#define LOKI_SMART_ASSERT_HIDDEN_CLASS LOKI_SMART_ASSERT_CLASS( LOKI_SMART_ASSERT_CLASS_NAME, LOKI_SMART_ASSERT_IGNORE_NAME ) + + +// --------------------------------------------------------------------- + +// @note This checks if LOKI_SMART_ASSERT_CONTEXT was defined already in +// case developers made their own context-creating macro. If you make +// your own context chain, follow the example here and expect SmartAssert +// to display the context information in the reverse order of how they +// are added here. (e.g. - The contexts are added in function-line-file +// order, but shown in file-line-function order.) +#ifndef LOKI_SMART_ASSERT_CONTEXT + + #ifdef LOKI_SMART_ASSERT_FUNCTION_EXISTS + #define LOKI_SMART_ASSERT_CONTEXT \ + Add( ::Loki::AssertContext( ::Loki::SmartAssertBase::FunctionDesc, LOKI_SMART_ASSERT_FUNCTION ) ). \ + Add( ::Loki::AssertContext( ::Loki::SmartAssertBase::LineDesc, __LINE__ ) ). \ + Add( ::Loki::AssertContext( ::Loki::SmartAssertBase::FileDesc, LOKI_SMART_ASSERT_FILE ) ) + #else + #define LOKI_SMART_ASSERT_CONTEXT \ + Add( ::Loki::AssertContext( ::Loki::SmartAssertBase::LineDesc, __LINE__ ) ). \ + Add( ::Loki::AssertContext( ::Loki::SmartAssertBase::FileDesc, LOKI_SMART_ASSERT_FILE ) ) + #endif + +#endif // LOKI_SMART_ASSERT_CONTEXT + + +// --------------------------------------------------------------------- + +#define LOKI_MAKE_SMART_ASSERT( class_name, ignore_var_name, expr ) \ + static bool ignore_var_name = false; \ + class class_name : public ::Loki::SmartAssert< ::Loki::CommandLineAssertPolicy > \ + { public: \ + typedef ::Loki::SmartAssert< ::Loki::CommandLineAssertPolicy > BaseClass; \ + class_name( bool * ignore, const char * expression ) \ + : BaseClass( ignore, expression ) {} \ + virtual ~class_name() {} \ + }; \ + if ( ignore_var_name || ( expr ) ) ; else \ + class_name( &ignore_var_name, #expr ).LOKI_SMART_ASSERT_CONTEXT + + +#ifdef LOKI_SMART_ASSERT_DEBUG + #define LOKI_SMART_ASSERT( expr ) \ + LOKI_MAKE_SMART_ASSERT( LOKI_SMART_ASSERT_CLASS_NAME, LOKI_SMART_ASSERT_IGNORE_NAME, (expr) ) + +#else + #define LOKI_SMART_ASSERT( expr ) \ + if ( true ) ; else \ + ::Loki::SmartAssert< ::Loki::CommandLineAssertPolicy >() + // Do nothing. Compiler should optimize away the else branch. +#endif + + +// --------------------------------------------------------------------- + +#define LOKI_MAKE_SMART_ASSERT_POLICIED( class_name, ignore_var_name, expr, policy ) \ + static bool ignore_var_name = false; \ + class class_name : public ::Loki::SmartAssert< policy > \ + { public: \ + typedef ::Loki::SmartAssert< policy > BaseClass; \ + class_name( bool * ignore, const char * expression ) \ + : BaseClass( ignore, expression ) {} \ + virtual ~class_name() {} \ + }; \ + if ( ignore_var_name || ( expr ) ) ; else \ + class_name( &ignore_var_name, #expr ).LOKI_SMART_ASSERT_CONTEXT + + +#ifdef LOKI_SMART_ASSERT_DEBUG + #define LOKI_SMART_ASSERT_POLICIED( expr, policy ) \ + LOKI_MAKE_SMART_ASSERT_POLICIED( LOKI_SMART_ASSERT_CLASS_NAME, LOKI_SMART_ASSERT_IGNORE_NAME, (expr), policy ) + +#else + #define LOKI_SMART_ASSERT_POLICIED( expr, policy ) \ + if ( true ) ; else \ + ::Loki::SmartAssert< policy >() + // Do nothing. Compiler should optimize away the else branch. +#endif + +// --------------------------------------------------------------------- + +#if defined( LOKI_DEFINED_NULLPTR ) + #undef LOKI_DEFINED_NULLPTR + #undef nullptr +#endif + +#if defined( _MSC_VER ) + #pragma warning( pop ) +#endif + +#endif // LOKI_SMART_ASSERT_HPP_INCLUDED Property changes on: trunk/include/loki/SmartAssert.hpp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Added: trunk/src/SmartAssert.cpp =================================================================== --- trunk/src/SmartAssert.cpp (rev 0) +++ trunk/src/SmartAssert.cpp 2013-06-19 02:23:00 UTC (rev 1184) @@ -0,0 +1,527 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2013 by Rich Sposato +// Code covered by the MIT License +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +//////////////////////////////////////////////////////////////////////////////// + + +#include <loki/SmartAssert.hpp> + +#if defined( _WIN32 ) || defined( __WIN32__ ) || defined( WIN32 ) + #include <Windows.h> +#endif + +#include <iostream> + +#include <cassert> +#include <cstdlib> + +#if defined( _MSC_VER ) + #pragma warning( push ) + #pragma warning( disable : 4365 ) + #pragma warning( disable : 4514 ) + #pragma warning( disable : 4710 ) + #pragma warning( disable : 4711 ) +#endif + +#if !defined( nullptr ) + #define nullptr 0 +#endif + + +using namespace ::std; + +namespace Loki +{ + +bool SmartAssertBase::s_alwaysIgnore = true; + +const char * const SmartAssertBase::FileDesc = "file"; +const char * const SmartAssertBase::LineDesc = "line"; +const char * const SmartAssertBase::FunctionDesc = "function"; + + +// --------------------------------------------------------------------- + +const char * AssertInfo::GetName( DataTypeTag tag ) +{ + switch ( tag ) + { + case Unknown: return "Unknown"; + case Boolean: return "boolean"; + case JustChar: return "char"; + case SignedChar: return "signed char"; + case UnsignedChar: return "char"; + case SignedShort: return "signed short"; + case UnsignedShort: return "unsigned short"; + case JustInt: return "int"; + case SignedInt: return "signed int"; + case UnsignedInt: return "unsigned int"; + case Long: return "long"; + case UnsignedLong: return "unsigned long"; + case LongInt: return "long int"; + case UnsignedLongInt: return "unsigned long int"; + case CharPtr: return "char *"; + case SignedCharPtr: return "signed char *"; + case UnsignedCharPtr: return "unsigned char *"; + case VoidPtr: return "void *"; + case Float: return "float"; + case Double: return "double"; + case LongDouble: return "long double"; + default: break; + } + return "undefined data type"; +} + +// --------------------------------------------------------------------- + +void AssertInfo::DataValue::Output( DataTypeTag theType ) const +{ + switch ( theType ) + { + case Unknown: + { + cout << "\t Error! Unknown data type! " << theType; + break; + } + case Boolean: + { + const char * message = m_bool ? "true" : "false"; + cout << message; + break; + } + case JustChar: + { + cout << m_char; + break; + } + case SignedChar: + { + cout << m_s_char; + break; + } + case UnsignedChar: + { + cout << m_u_char; + break; + } + case SignedShort: + { + cout << m_s_short; + break; + } + case UnsignedShort: + { + cout << m_u_short; + break; + } + case JustInt: + { + cout << m_int; + break; + } + case SignedInt: + { + cout << m_int; + break; + } + case UnsignedInt: + { + cout << m_u_int; + break; + } + case Long: + { + cout << m_long; + break; + } + case UnsignedLong: + { + cout << m_u_long; + break; + } + case LongInt: + { + cout << m_s_long_int; + break; + } + case UnsignedLongInt: + { + cout << m_u_long_int; + break; + } + case CharPtr: + { + cout << m_p_char; + break; + } + case SignedCharPtr: + { + cout << m_p_s_char; + break; + } + case UnsignedCharPtr: + { + cout << m_p_u_char; + break; + } + case VoidPtr: + { + cout << m_p_v; + break; + } + case Float: + { + cout << m_float; + break; + } + case Double: + { + cout << m_double; + break; + } + case LongDouble: + { + cout << m_l_double; + break; + } + default: + { + cout << "\t Error! Undefined data type! " << theType; + break; + } + } +} + +// --------------------------------------------------------------------- + +void AssertInfo::Output() const +{ + cout << "\t" << GetName( m_type ) << ": "; + m_value.Output( m_type ); + cout << endl; +} + +// --------------------------------------------------------------------- + +AssertContext::AssertContext( const char * description, unsigned int line ) + : m_line( line ) + , m_value( nullptr ) + , m_description( description ) + , m_next( nullptr ) +{ +} + +// --------------------------------------------------------------------- + +AssertContext::AssertContext( const char * description, const char * value ) + : m_line( 0 ) + , m_value( value ) + , m_description( description ) + , m_next( nullptr ) +{ +} + +// --------------------------------------------------------------------- + +void AssertContext::Output() const +{ + cout << m_description << ": "; + if ( m_value != nullptr ) + { + cout << m_value; + } + else + { + cout << m_line; + } +} + +// --------------------------------------------------------------------- + +const char * SmartAssertBase::GetName( SeverityLevel level ) +{ + switch ( level ) + { + case Info_: return "Info"; + case Warn_: return "Warning"; + case Error_: return "Error"; + case Fatal_: return "Fatal"; + } + return "unknown"; +} + +// --------------------------------------------------------------------- + +SmartAssertBase::SmartAssertBase() + : m_context( nullptr ) + , m_info( nullptr ) + , m_level( Warn_ ) + , m_ignore( &s_alwaysIgnore ) + , m_expression( nullptr ) + , m_message( nullptr ) + , m_handled( false ) +{ +} + +// --------------------------------------------------------------------- + +SmartAssertBase::SmartAssertBase( bool * ignore, const char * expression ) + : m_context( nullptr ) + , m_info( nullptr ) + , m_level( Fatal_ ) ///< @note Default level is fatal to match behavior of assert. + , m_ignore( ignore ) + , m_expression( expression ) + , m_message( nullptr ) + , m_handled( false ) +{ +} + +// --------------------------------------------------------------------- + +SmartAssertBase::~SmartAssertBase() +{ + if ( m_handled ) + { + return; + } + + try + { + CallOutput(); + if ( ( Fatal_ == m_level ) || ( Error_ == m_level ) ) + { + AbortNow(); + } + } + catch ( ... ) + { + if ( ( Fatal_ == m_level ) || ( Error_ == m_level ) ) + { + // In other situations, I might allow a destructor to do nothing + // when an exception occurs, but since this exception occurred + // while processing a failed assertion, it is probably not safe + // to ignore the exception. Just end the program abruptly. + ::std::abort(); + } + } +} + +// --------------------------------------------------------------------- + +SmartAssertBase & SmartAssertBase::AddContext( const AssertContext & context ) +{ + // Contexts are always added to the head of the linked-list since that + // is cheaper than traversing the list every time, but the list is in + // reverse order from how the entries are declared. + assert( m_context != &context ); + context.m_next = m_context; + m_context = &context; + return *this; +} + +// --------------------------------------------------------------------- + +SmartAssertBase & SmartAssertBase::AddInfo( const AssertInfo & info ) +{ + // AssertInfo's are always added to the head of the linked-list since + // that is cheaper than traversing the list every time, but the list + // is in reverse order from how the entries are declared. + assert( m_info != &info ); + info.m_next = m_info; + m_info = &info; + return *this; +} + +// --------------------------------------------------------------------- + +void SmartAssertBase::CallOutput() const +{ + CommandLineAssertPolicy::Output( this ); +} + +// --------------------------------------------------------------------- + +void SmartAssertBase::CallDebugger() const +{ + CommandLineAssertPolicy::Debugger( this ); +} + +// --------------------------------------------------------------------- + +SmartAssertBase::UserResponse SmartAssertBase::AskUser() const +{ + return CommandLineAssertPolicy::AskUser( this ); +} + +// --------------------------------------------------------------------- + +void SmartAssertBase::AbortNow() const +{ + CommandLineAssertPolicy::AbortNow( this ); +} + +// --------------------------------------------------------------------- + +void SmartAssertBase::HandleFailure() +{ + m_handled = true; + + try + { + if ( Info_ == m_level ) + { + CallOutput(); + return; + } + CallOutput(); + if ... [truncated message content] |
From: <ric...@us...> - 2012-04-03 05:47:02
|
Revision: 1183 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1183&view=rev Author: rich_sposato Date: 2012-04-03 05:46:56 +0000 (Tue, 03 Apr 2012) Log Message: ----------- Made documentation comment consistent. Modified Paths: -------------- trunk/include/loki/LevelMutex.h Modified: trunk/include/loki/LevelMutex.h =================================================================== --- trunk/include/loki/LevelMutex.h 2012-04-03 05:45:23 UTC (rev 1182) +++ trunk/include/loki/LevelMutex.h 2012-04-03 05:46:56 UTC (rev 1183) @@ -718,8 +718,8 @@ either pthreads or the Windows CRITICAL_SECTION. If you want to use a mutex mechanism besides one of those, then all you have to do is provide a class which wraps the mutex and implements these functions. - explicit SpinLevelMutex( unsigned int level ); - virtual ~SpinLevelMutex( void ); + explicit MutexPolicy( unsigned int level ); + virtual ~MutexPolicy( void ); virtual MutexErrors::Type Lock( void ) volatile; virtual MutexErrors::Type TryLock( void ) volatile; virtual MutexErrors::Type Unlock( void ) volatile; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2012-04-03 05:45:29
|
Revision: 1182 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1182&view=rev Author: rich_sposato Date: 2012-04-03 05:45:23 +0000 (Tue, 03 Apr 2012) Log Message: ----------- Added overloaded version of file. Modified Paths: -------------- trunk/src/LevelMutex.cpp Modified: trunk/src/LevelMutex.cpp =================================================================== --- trunk/src/LevelMutex.cpp 2012-04-02 06:07:08 UTC (rev 1181) +++ trunk/src/LevelMutex.cpp 2012-04-03 05:45:23 UTC (rev 1182) @@ -671,6 +671,14 @@ bool LevelMutexInfo::IsNotLockedByCurrentThread( void ) const volatile { + const LevelMutexInfo * pThis = const_cast< const LevelMutexInfo * >( this ); + return pThis->IsNotLockedByCurrentThread(); +} + +// ---------------------------------------------------------------------------- + +bool LevelMutexInfo::IsNotLockedByCurrentThread( void ) const +{ if ( !IsLocked() ) return true; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2012-04-02 06:07:14
|
Revision: 1181 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1181&view=rev Author: rich_sposato Date: 2012-04-02 06:07:08 +0000 (Mon, 02 Apr 2012) Log Message: ----------- Use more recent project files. Modified Paths: -------------- trunk/Loki.workspace Modified: trunk/Loki.workspace =================================================================== --- trunk/Loki.workspace 2012-04-02 06:05:04 UTC (rev 1180) +++ trunk/Loki.workspace 2012-04-02 06:07:08 UTC (rev 1181) @@ -14,7 +14,7 @@ <Project filename="test/Factory/Factory.cbp" /> <Project filename="test/flex_string/flex_string.cbp" /> <Project filename="test/Function/Function.cbp" /> - <Project filename="test/LevelMutex/LevelMutex.cbp"> + <Project filename="test/LevelMutex/LevelMutex.cbp" active="1"> <Depends filename="Loki.cbp" /> </Project> <Project filename="test/Lockable/Lockable.cbp"> @@ -47,7 +47,7 @@ </Project> <Project filename="test/ThreadLocal/ThreadLocal.cbp" /> <Project filename="test/Visitor/Visitor.cbp" /> - <Project filename="test/SmallObj/SmallObjSingleton.cbp" active="1"> + <Project filename="test/SmallObj/SmallObjSingleton.cbp"> <Depends filename="Loki.cbp" /> </Project> </Workspace> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2012-04-02 06:05:11
|
Revision: 1180 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1180&view=rev Author: rich_sposato Date: 2012-04-02 06:05:04 +0000 (Mon, 02 Apr 2012) Log Message: ----------- Overloaded functions for volatile to make better use of Memento and Loki::Checker. Modified Paths: -------------- trunk/include/loki/LevelMutex.h trunk/src/LevelMutex.cpp Modified: trunk/include/loki/LevelMutex.h =================================================================== --- trunk/include/loki/LevelMutex.h 2012-04-02 06:01:51 UTC (rev 1179) +++ trunk/include/loki/LevelMutex.h 2012-04-02 06:05:04 UTC (rev 1180) @@ -272,11 +272,15 @@ { public: - explicit Memento( const volatile LevelMutexInfo & mutex ); + explicit Memento( const LevelMutexInfo & mutex ); - bool operator == ( const volatile LevelMutexInfo & mutex ) const; + bool operator == ( const LevelMutexInfo & mutex ) const; private: + + /// Copy-assignment operator is not implemented. + Memento & operator = ( const Memento & ); + /// Level of this mutex. const unsigned int m_level; @@ -295,7 +299,7 @@ exception. The checkers only get used in debug builds, and get optimized away in release builds. */ - typedef ::Loki::CheckFor< volatile LevelMutexInfo, Memento > CheckFor; + typedef ::Loki::CheckFor< const LevelMutexInfo, Memento > CheckFor; /** @class MutexUndoer Undoes actions by MultiLock if an exception occurs. It keeps track of @@ -362,13 +366,13 @@ /** Returns true if no class invariant broken, otherwise asserts. This function only gets called in debug builds. */ - bool IsValid( void ) const; + bool IsValid2( void ) const; /// Returns true if all pre-conditions for PostLock function are valid. - bool PostLockValidator( void ) const volatile; + bool PostLockValidator( void ) const; /// Returns true if all pre-conditions for PreUnlock function are valid. - bool PreUnlockValidator( void ) const volatile; + bool PreUnlockValidator( void ) const; private: @@ -395,16 +399,22 @@ /// Called only by MultiUnlock to unlock each particular mutex within a container. virtual MutexErrors::Type UnlockThis( void ) volatile = 0; + void PostLock( void ); + /** The actual implementation of IsLockedByCurrentThread. This does not do any invariant checking because the functions which call it already have. */ bool IsLockedByCurrentThreadImpl( void ) const volatile; + bool IsLockedByCurrentThreadImpl( void ) const; + /** Does just the opposite of IsLockedByCurrentThread. Called as a post-condition check by another function. */ bool IsNotLockedByCurrentThread( void ) const volatile; + bool IsNotLockedByCurrentThread( void ) const; + /// Pointer to singly-linked list of mutexes locked by the current thread. static LOKI_THREAD_LOCAL volatile LevelMutexInfo * s_currentMutex; Modified: trunk/src/LevelMutex.cpp =================================================================== --- trunk/src/LevelMutex.cpp 2012-04-02 06:01:51 UTC (rev 1179) +++ trunk/src/LevelMutex.cpp 2012-04-02 06:05:04 UTC (rev 1180) @@ -232,7 +232,7 @@ // ---------------------------------------------------------------------------- -LevelMutexInfo::Memento::Memento( const volatile LevelMutexInfo & mutex ) : +LevelMutexInfo::Memento::Memento( const LevelMutexInfo & mutex ) : m_level( mutex.m_level ), m_count( mutex.m_count ), m_previous( mutex.m_previous ), @@ -243,7 +243,7 @@ // ---------------------------------------------------------------------------- -bool LevelMutexInfo::Memento::operator == ( const volatile LevelMutexInfo & mutex ) const +bool LevelMutexInfo::Memento::operator == ( const LevelMutexInfo & mutex ) const { assert( this != nullptr ); @@ -594,6 +594,14 @@ bool LevelMutexInfo::IsValid( void ) const volatile { + const LevelMutexInfo * pThis = const_cast< const LevelMutexInfo * >( this ); + return pThis->IsValid2(); +} + +// ---------------------------------------------------------------------------- + +bool LevelMutexInfo::IsValid2( void ) const +{ assert( nullptr != this ); assert( LevelMutexInfo::UnlockedLevel != m_level ); assert( m_previous != this ); @@ -604,14 +612,6 @@ // ---------------------------------------------------------------------------- -bool LevelMutexInfo::IsValid( void ) const -{ - const volatile LevelMutexInfo * pThis = const_cast< const volatile LevelMutexInfo * >( this ); - return pThis->IsValid(); -} - -// ---------------------------------------------------------------------------- - void LevelMutexInfo::IncrementCount( void ) volatile { assert( IsValid() ); @@ -636,7 +636,8 @@ // gets called by various functions that are called to clean up after an exception // is thrown LOKI_MUTEX_DEBUG_CODE( - CheckFor::NoChange checker( this, &LevelMutexInfo::IsValid ); + const LevelMutexInfo * pThis = const_cast< const LevelMutexInfo * >( this ); + CheckFor::NoChange checker( pThis, &LevelMutexInfo::IsValid2 ); (void)checker; ) return IsLockedByCurrentThreadImpl(); @@ -646,6 +647,14 @@ bool LevelMutexInfo::IsLockedByCurrentThreadImpl( void ) const volatile { + const LevelMutexInfo * pThis = const_cast< const LevelMutexInfo * >( this ); + return pThis->IsLockedByCurrentThreadImpl(); +} + +// ---------------------------------------------------------------------------- + +bool LevelMutexInfo::IsLockedByCurrentThreadImpl( void ) const +{ if ( !IsLocked() ) return false; const volatile LevelMutexInfo * mutex = s_currentMutex; @@ -681,7 +690,8 @@ bool LevelMutexInfo::IsRecentLock( void ) const volatile { LOKI_MUTEX_DEBUG_CODE( - CheckFor::NoThrowOrChange checker( this, &LevelMutexInfo::IsValid ); + const LevelMutexInfo * pThis = const_cast< const LevelMutexInfo * >( this ); + CheckFor::NoThrowOrChange checker( pThis, &LevelMutexInfo::IsValid2 ); (void)checker; ) @@ -705,7 +715,8 @@ bool LevelMutexInfo::IsRecentLock( std::size_t count ) const volatile { LOKI_MUTEX_DEBUG_CODE( - CheckFor::NoThrowOrChange checker( this, &LevelMutexInfo::IsValid ); + const LevelMutexInfo * pThis = const_cast< const LevelMutexInfo * >( this ); + CheckFor::NoThrowOrChange checker( pThis, &LevelMutexInfo::IsValid2 ); (void)checker; ) @@ -728,7 +739,8 @@ bool LevelMutexInfo::IsLockedByAnotherThread( void ) const volatile { LOKI_MUTEX_DEBUG_CODE( - CheckFor::NoThrowOrChange checker( this, &LevelMutexInfo::IsValid ); + const LevelMutexInfo * pThis = const_cast< const LevelMutexInfo * >( this ); + CheckFor::NoThrowOrChange checker( pThis, &LevelMutexInfo::IsValid2 ); (void)checker; ) @@ -743,7 +755,7 @@ // ---------------------------------------------------------------------------- -bool LevelMutexInfo::PostLockValidator( void ) const volatile +bool LevelMutexInfo::PostLockValidator( void ) const { assert( 0 == m_count ); assert( nullptr == m_previous ); @@ -757,8 +769,17 @@ void LevelMutexInfo::PostLock( void ) volatile { + LevelMutexInfo * pThis = const_cast< LevelMutexInfo * >( this ); + pThis->PostLock(); +} + +// ---------------------------------------------------------------------------- + +void LevelMutexInfo::PostLock( void ) +{ LOKI_MUTEX_DEBUG_CODE( - CheckFor::NoThrow checker( this, &LevelMutexInfo::IsValid, + const LevelMutexInfo * pThis = const_cast< const LevelMutexInfo * >( this ); + CheckFor::NoThrow checker( pThis, &LevelMutexInfo::IsValid2, &LevelMutexInfo::PostLockValidator, &LevelMutexInfo::IsLockedByCurrentThreadImpl ); (void)checker; ) @@ -775,7 +796,7 @@ // ---------------------------------------------------------------------------- -bool LevelMutexInfo::PreUnlockValidator( void ) const volatile +bool LevelMutexInfo::PreUnlockValidator( void ) const { assert( 1 == m_count ); assert( nullptr != s_currentMutex ); @@ -790,9 +811,10 @@ void LevelMutexInfo::PreUnlock( void ) volatile { LOKI_MUTEX_DEBUG_CODE( + const LevelMutexInfo * pThis = const_cast< const LevelMutexInfo * >( this ); // This must use CheckFor::Invariants instead of CheckFor::NoThrow because the // function gets called when MultiLock has to clean up after an exception. - CheckFor::Invariants checker( this, &LevelMutexInfo::IsValid, + CheckFor::Invariants checker( pThis, &LevelMutexInfo::IsValid2, &LevelMutexInfo::PreUnlockValidator, &LevelMutexInfo::IsNotLockedByCurrentThread ); (void)checker; ) @@ -812,7 +834,8 @@ MutexErrors::Type LevelMutexInfo::PreLockCheck( bool forTryLock ) volatile { LOKI_MUTEX_DEBUG_CODE( - CheckFor::NoThrow checker( this, &LevelMutexInfo::IsValid ); + const LevelMutexInfo * pThis = const_cast< const LevelMutexInfo * >( this ); + CheckFor::NoThrow checker( pThis, &LevelMutexInfo::IsValid2 ); (void)checker; ) @@ -849,7 +872,8 @@ MutexErrors::Type LevelMutexInfo::PreUnlockCheck( void ) volatile { LOKI_MUTEX_DEBUG_CODE( - CheckFor::NoThrow checker( this, &LevelMutexInfo::IsValid ); + const LevelMutexInfo * pThis = const_cast< const LevelMutexInfo * >( this ); + CheckFor::NoThrow checker( pThis, &LevelMutexInfo::IsValid2 ); (void)checker; ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2012-04-02 06:01:57
|
Revision: 1179 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1179&view=rev Author: rich_sposato Date: 2012-04-02 06:01:51 +0000 (Mon, 02 Apr 2012) Log Message: ----------- Fixed bug 3509427 by adding use of Loki::TypeTraits. Modified Paths: -------------- trunk/include/loki/SafeFormat.h trunk/src/SafeFormat.cpp Modified: trunk/include/loki/SafeFormat.h =================================================================== --- trunk/include/loki/SafeFormat.h 2012-04-02 05:49:21 UTC (rev 1178) +++ trunk/include/loki/SafeFormat.h 2012-04-02 06:01:51 UTC (rev 1179) @@ -44,6 +44,7 @@ #include <iostream> #include <loki/LokiExport.h> +#include <loki/TypeTraits.h> // long is 32 bit on 64-bit Windows! @@ -132,7 +133,7 @@ another device type. It is not for public use. */ template < class Device2 > - PrintfState< Device2, Char > ChangeDevice( Device2 & device ) const + PrintfState< Device2, Char > ChangeDevice( typename Loki::TypeTraits< Device2 >::ParameterType device ) const { return PrintfState< Device2, Char >( device, format_, width_, prec_, flags_, result_ ); } Modified: trunk/src/SafeFormat.cpp =================================================================== --- trunk/src/SafeFormat.cpp 2012-04-02 05:49:21 UTC (rev 1178) +++ trunk/src/SafeFormat.cpp 2012-04-02 06:01:51 UTC (rev 1179) @@ -70,7 +70,7 @@ const PrintfState< ::std::string &, char > state1( buffer, format ); ::std::fwrite( buffer.c_str(), 1, buffer.size(), stdout ); ::std::FILE * f = stdout; - PrintfState< std::FILE *, char > printState2( state1.ChangeDevice( f ) ); + PrintfState< std::FILE *, char > printState2( state1.ChangeDevice< ::std::FILE * >( f ) ); return printState2; } @@ -79,7 +79,7 @@ const PrintfState< ::std::string &, char > state1( buffer, format.c_str() ); ::std::fwrite( buffer.c_str(), 1, buffer.size(), stdout ); ::std::FILE * f = stdout; - PrintfState< std::FILE *, char > printState2( state1.ChangeDevice( f ) ); + PrintfState< std::FILE *, char > printState2( state1.ChangeDevice< ::std::FILE * >( f ) ); return printState2; } @@ -87,7 +87,7 @@ ::std::string buffer; const PrintfState< ::std::string &, char > state1( buffer, format ); ::std::fwrite( buffer.c_str(), 1, buffer.size(), f ); - PrintfState< std::FILE *, char > printState2 = state1.ChangeDevice( f ); + PrintfState< std::FILE *, char > printState2 = state1.ChangeDevice< ::std::FILE * >( f ); return printState2; } @@ -95,7 +95,7 @@ ::std::string buffer; const PrintfState< ::std::string &, char > state1( buffer, format.c_str() ); ::std::fwrite( buffer.c_str(), 1, buffer.size(), f ); - PrintfState< std::FILE *, char > printState2 = state1.ChangeDevice( f ); + PrintfState< std::FILE *, char > printState2 = state1.ChangeDevice< ::std::FILE * >( f ); return printState2; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2012-04-02 05:49:27
|
Revision: 1178 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1178&view=rev Author: rich_sposato Date: 2012-04-02 05:49:21 +0000 (Mon, 02 Apr 2012) Log Message: ----------- Put braces around assert statement. Modified Paths: -------------- trunk/include/loki/Checker.h Modified: trunk/include/loki/Checker.h =================================================================== --- trunk/include/loki/Checker.h 2011-11-07 23:56:57 UTC (rev 1177) +++ trunk/include/loki/Checker.h 2012-04-02 05:49:21 UTC (rev 1178) @@ -524,7 +524,9 @@ { assert( Check() ); if ( 0 != m_pre ) + { assert( ( m_host->*( m_pre ) )() ); + } } /** The destructor checks if any Host invariants failed, and then calls the @@ -535,7 +537,9 @@ { assert( Check() ); if ( 0 != m_post ) + { assert( ( m_host->*( m_post ) )() ); + } assert( Ep::Check( m_host ) ); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2011-11-07 23:57:03
|
Revision: 1177 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1177&view=rev Author: rich_sposato Date: 2011-11-07 23:56:57 +0000 (Mon, 07 Nov 2011) Log Message: ----------- Changed some parameters. Modified Paths: -------------- trunk/Loki.cbp Modified: trunk/Loki.cbp =================================================================== --- trunk/Loki.cbp 2011-11-07 23:55:30 UTC (rev 1176) +++ trunk/Loki.cbp 2011-11-07 23:56:57 UTC (rev 1177) @@ -6,37 +6,38 @@ <Option compiler="cygwin" /> <Build> <Target title="Debug_GCC"> - <Option output=".\lib\GCC\Loki_D.a" prefix_auto="0" extension_auto="0" /> + <Option output="./lib/GCC/Loki_D.a" prefix_auto="0" extension_auto="0" /> <Option working_dir="" /> - <Option object_output="obj\Debug_GCC\" /> + <Option object_output="obj/Debug_GCC/" /> <Option type="2" /> <Option compiler="gcc" /> <Option createDefFile="1" /> <Compiler> + <Add option="-g" /> <Add option="-W" /> - <Add option="-g" /> + <Add option="-DDEBUG" /> <Add directory="." /> - <Add directory=".\include" /> - <Add directory=".\include\loki" /> + <Add directory="./include" /> + <Add directory="./include/loki" /> </Compiler> </Target> <Target title="Release_GCC"> - <Option output=".\lib\GCC\Loki.a" prefix_auto="0" extension_auto="0" /> + <Option output="./lib/GCC/Loki.a" prefix_auto="0" extension_auto="0" /> <Option working_dir="" /> - <Option object_output="obj\Release_GCC\" /> + <Option object_output="obj/Release_GCC/" /> <Option type="2" /> <Option compiler="gcc" /> <Option createDefFile="1" /> <Compiler> <Add option="-W" /> - <Add directory=".\include\loki" /> - <Add directory=".\include" /> + <Add directory="./include/loki" /> + <Add directory="./include" /> </Compiler> </Target> <Target title="Debug_Cygwin"> - <Option output=".\lib\Cygwin\Loki_D.a" prefix_auto="0" extension_auto="0" /> + <Option output="./lib/Cygwin/Loki_D.a" prefix_auto="0" extension_auto="0" /> <Option working_dir="" /> - <Option object_output="obj\Debug_Cygwin\" /> + <Option object_output="obj/Debug_Cygwin/" /> <Option type="2" /> <Option compiler="cygwin" /> <Option createDefFile="1" /> @@ -44,88 +45,88 @@ <Add option="-W" /> <Add option="-g" /> <Add directory="." /> - <Add directory=".\include" /> - <Add directory=".\include\loki" /> + <Add directory="./include" /> + <Add directory="./include/loki" /> </Compiler> </Target> <Target title="Release_Cygwin"> - <Option output=".\lib\Cygwin\Loki.a" prefix_auto="0" extension_auto="0" /> + <Option output="./lib/Cygwin/Loki.a" prefix_auto="0" extension_auto="0" /> <Option working_dir="" /> - <Option object_output="obj\Release_Cygwin\" /> + <Option object_output="obj/Release_Cygwin/" /> <Option type="2" /> <Option compiler="cygwin" /> <Option createDefFile="1" /> <Compiler> <Add option="-W" /> - <Add directory=".\include\loki" /> - <Add directory=".\include" /> + <Add directory="./include/loki" /> + <Add directory="./include" /> </Compiler> </Target> </Build> - <Unit filename="include\loki\AbstractFactory.h" /> - <Unit filename="include\loki\Allocator.h" /> - <Unit filename="include\loki\AssocVector.h" /> - <Unit filename="include\loki\CachedFactory.h" /> - <Unit filename="include\loki\CheckReturn.h" /> - <Unit filename="include\loki\Checker.h" /> - <Unit filename="include\loki\ConstPolicy.h" /> - <Unit filename="include\loki\DataGenerators.h" /> - <Unit filename="include\loki\EmptyType.h" /> - <Unit filename="include\loki\Factory.h" /> - <Unit filename="include\loki\Function.h" /> - <Unit filename="include\loki\Functor.h" /> - <Unit filename="include\loki\HierarchyGenerators.h" /> - <Unit filename="include\loki\Key.h" /> - <Unit filename="include\loki\LevelMutex.h" /> - <Unit filename="include\loki\LockingPtr.h" /> - <Unit filename="include\loki\LokiExport.h" /> - <Unit filename="include\loki\LokiTypeInfo.h" /> - <Unit filename="include\loki\MultiMethods.h" /> - <Unit filename="include\loki\NullType.h" /> - <Unit filename="include\loki\OrderedStatic.h" /> - <Unit filename="include\loki\Pimpl.h" /> - <Unit filename="include\loki\RefToValue.h" /> - <Unit filename="include\loki\Register.h" /> - <Unit filename="include\loki\SPCachedFactory.h" /> - <Unit filename="include\loki\SafeBits.h" /> - <Unit filename="include\loki\SafeFormat.h" /> - <Unit filename="include\loki\ScopeGuard.h" /> - <Unit filename="include\loki\Sequence.h" /> - <Unit filename="include\loki\Singleton.h" /> - <Unit filename="include\loki\SmallObj.h" /> - <Unit filename="include\loki\SmartPtr.h" /> - <Unit filename="include\loki\StrongPtr.h" /> - <Unit filename="include\loki\ThreadLocal.h" /> - <Unit filename="include\loki\Threads.h" /> - <Unit filename="include\loki\Tuple.h" /> - <Unit filename="include\loki\TypeManip.h" /> - <Unit filename="include\loki\TypeTraits.h" /> - <Unit filename="include\loki\Typelist.h" /> - <Unit filename="include\loki\TypelistMacros.h" /> - <Unit filename="include\loki\Visitor.h" /> - <Unit filename="include\loki\flex\allocatorstringstorage.h" /> - <Unit filename="include\loki\flex\cowstringopt.h" /> - <Unit filename="include\loki\flex\flex_string.h" /> - <Unit filename="include\loki\flex\flex_string_details.h" /> - <Unit filename="include\loki\flex\flex_string_shell.h" /> - <Unit filename="include\loki\flex\simplestringstorage.h" /> - <Unit filename="include\loki\flex\smallstringopt.h" /> - <Unit filename="include\loki\flex\vectorstringstorage.h" /> - <Unit filename="include\loki\static_check.h" /> - <Unit filename="include\loki\yasli\platform.h" /> - <Unit filename="include\loki\yasli\random.h" /> - <Unit filename="include\loki\yasli\yasli_fill_iterator.h" /> - <Unit filename="include\loki\yasli\yasli_memory.h" /> - <Unit filename="include\loki\yasli\yasli_protocols.h" /> - <Unit filename="include\loki\yasli\yasli_traits.h" /> - <Unit filename="include\loki\yasli\yasli_vector.h" /> - <Unit filename="src\LevelMutex.cpp" /> - <Unit filename="src\OrderedStatic.cpp" /> - <Unit filename="src\SafeFormat.cpp" /> - <Unit filename="src\Singleton.cpp" /> - <Unit filename="src\SmallObj.cpp" /> - <Unit filename="src\SmartPtr.cpp" /> - <Unit filename="src\StrongPtr.cpp" /> + <Unit filename="include/loki/AbstractFactory.h" /> + <Unit filename="include/loki/Allocator.h" /> + <Unit filename="include/loki/AssocVector.h" /> + <Unit filename="include/loki/CachedFactory.h" /> + <Unit filename="include/loki/CheckReturn.h" /> + <Unit filename="include/loki/Checker.h" /> + <Unit filename="include/loki/ConstPolicy.h" /> + <Unit filename="include/loki/DataGenerators.h" /> + <Unit filename="include/loki/EmptyType.h" /> + <Unit filename="include/loki/Factory.h" /> + <Unit filename="include/loki/Function.h" /> + <Unit filename="include/loki/Functor.h" /> + <Unit filename="include/loki/HierarchyGenerators.h" /> + <Unit filename="include/loki/Key.h" /> + <Unit filename="include/loki/LevelMutex.h" /> + <Unit filename="include/loki/LockingPtr.h" /> + <Unit filename="include/loki/LokiExport.h" /> + <Unit filename="include/loki/LokiTypeInfo.h" /> + <Unit filename="include/loki/MultiMethods.h" /> + <Unit filename="include/loki/NullType.h" /> + <Unit filename="include/loki/OrderedStatic.h" /> + <Unit filename="include/loki/Pimpl.h" /> + <Unit filename="include/loki/RefToValue.h" /> + <Unit filename="include/loki/Register.h" /> + <Unit filename="include/loki/SPCachedFactory.h" /> + <Unit filename="include/loki/SafeBits.h" /> + <Unit filename="include/loki/SafeFormat.h" /> + <Unit filename="include/loki/ScopeGuard.h" /> + <Unit filename="include/loki/Sequence.h" /> + <Unit filename="include/loki/Singleton.h" /> + <Unit filename="include/loki/SmallObj.h" /> + <Unit filename="include/loki/SmartPtr.h" /> + <Unit filename="include/loki/StrongPtr.h" /> + <Unit filename="include/loki/ThreadLocal.h" /> + <Unit filename="include/loki/Threads.h" /> + <Unit filename="include/loki/Tuple.h" /> + <Unit filename="include/loki/TypeManip.h" /> + <Unit filename="include/loki/TypeTraits.h" /> + <Unit filename="include/loki/Typelist.h" /> + <Unit filename="include/loki/TypelistMacros.h" /> + <Unit filename="include/loki/Visitor.h" /> + <Unit filename="include/loki/flex/allocatorstringstorage.h" /> + <Unit filename="include/loki/flex/cowstringopt.h" /> + <Unit filename="include/loki/flex/flex_string.h" /> + <Unit filename="include/loki/flex/flex_string_details.h" /> + <Unit filename="include/loki/flex/flex_string_shell.h" /> + <Unit filename="include/loki/flex/simplestringstorage.h" /> + <Unit filename="include/loki/flex/smallstringopt.h" /> + <Unit filename="include/loki/flex/vectorstringstorage.h" /> + <Unit filename="include/loki/static_check.h" /> + <Unit filename="include/loki/yasli/platform.h" /> + <Unit filename="include/loki/yasli/random.h" /> + <Unit filename="include/loki/yasli/yasli_fill_iterator.h" /> + <Unit filename="include/loki/yasli/yasli_memory.h" /> + <Unit filename="include/loki/yasli/yasli_protocols.h" /> + <Unit filename="include/loki/yasli/yasli_traits.h" /> + <Unit filename="include/loki/yasli/yasli_vector.h" /> + <Unit filename="src/LevelMutex.cpp" /> + <Unit filename="src/OrderedStatic.cpp" /> + <Unit filename="src/SafeFormat.cpp" /> + <Unit filename="src/Singleton.cpp" /> + <Unit filename="src/SmallObj.cpp" /> + <Unit filename="src/SmartPtr.cpp" /> + <Unit filename="src/StrongPtr.cpp" /> <Extensions> <code_completion /> <envvars /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2011-11-07 23:55:37
|
Revision: 1176 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1176&view=rev Author: rich_sposato Date: 2011-11-07 23:55:30 +0000 (Mon, 07 Nov 2011) Log Message: ----------- Added Memento class to prove strong exception safety. Removed useless lines. Modified Paths: -------------- trunk/src/LevelMutex.cpp Modified: trunk/src/LevelMutex.cpp =================================================================== --- trunk/src/LevelMutex.cpp 2011-11-07 23:54:58 UTC (rev 1175) +++ trunk/src/LevelMutex.cpp 2011-11-07 23:55:30 UTC (rev 1176) @@ -232,6 +232,38 @@ // ---------------------------------------------------------------------------- +LevelMutexInfo::Memento::Memento( const volatile LevelMutexInfo & mutex ) : + m_level( mutex.m_level ), + m_count( mutex.m_count ), + m_previous( mutex.m_previous ), + m_locked( mutex.IsLockedByCurrentThreadImpl() ) +{ + assert( this != nullptr ); +} + +// ---------------------------------------------------------------------------- + +bool LevelMutexInfo::Memento::operator == ( const volatile LevelMutexInfo & mutex ) const +{ + assert( this != nullptr ); + + if ( m_locked && mutex.IsLockedByCurrentThreadImpl() ) + { + // If the current thread still has a lock on the mutex, then make + // sure no values have changed. + if ( m_level != mutex.m_level ) + return false; + if ( m_count != mutex.m_count ) + return false; + if ( m_previous != mutex.m_previous ) + return false; + } + + return true; +} + +// ---------------------------------------------------------------------------- + LevelMutexInfo::MutexUndoer::MutexUndoer( MutexContainer & mutexes ) : m_mutexes( mutexes ), m_here( mutexes.end() ) @@ -572,6 +604,14 @@ // ---------------------------------------------------------------------------- +bool LevelMutexInfo::IsValid( void ) const +{ + const volatile LevelMutexInfo * pThis = const_cast< const volatile LevelMutexInfo * >( this ); + return pThis->IsValid(); +} + +// ---------------------------------------------------------------------------- + void LevelMutexInfo::IncrementCount( void ) volatile { assert( IsValid() ); @@ -592,8 +632,20 @@ bool LevelMutexInfo::IsLockedByCurrentThread( void ) const volatile { - LOKI_MUTEX_DEBUG_CODE( CheckFor::NoChangeOrThrow checker( this, &IsValid() ); (void)checker; ) + // This function could call CheckFor::NoThrowOrChange - except that this function + // gets called by various functions that are called to clean up after an exception + // is thrown + LOKI_MUTEX_DEBUG_CODE( + CheckFor::NoChange checker( this, &LevelMutexInfo::IsValid ); + (void)checker; + ) + return IsLockedByCurrentThreadImpl(); +} +// ---------------------------------------------------------------------------- + +bool LevelMutexInfo::IsLockedByCurrentThreadImpl( void ) const volatile +{ if ( !IsLocked() ) return false; const volatile LevelMutexInfo * mutex = s_currentMutex; @@ -608,9 +660,30 @@ // ---------------------------------------------------------------------------- +bool LevelMutexInfo::IsNotLockedByCurrentThread( void ) const volatile +{ + if ( !IsLocked() ) + return true; + + const volatile LevelMutexInfo * mutex = s_currentMutex; + while ( nullptr != mutex ) + { + if ( this == mutex ) + return false; + mutex = mutex->m_previous; + } + + return true; +} + +// ---------------------------------------------------------------------------- + bool LevelMutexInfo::IsRecentLock( void ) const volatile { - LOKI_MUTEX_DEBUG_CODE( CheckFor::NoChangeOrThrow checker( this, &IsValid() ); (void)checker; ) + LOKI_MUTEX_DEBUG_CODE( + CheckFor::NoThrowOrChange checker( this, &LevelMutexInfo::IsValid ); + (void)checker; + ) if ( 0 == m_count ) return false; @@ -631,7 +704,10 @@ bool LevelMutexInfo::IsRecentLock( std::size_t count ) const volatile { - LOKI_MUTEX_DEBUG_CODE( CheckFor::NoChangeOrThrow checker( this, &IsValid() ); (void)checker; ) + LOKI_MUTEX_DEBUG_CODE( + CheckFor::NoThrowOrChange checker( this, &LevelMutexInfo::IsValid ); + (void)checker; + ) if ( 0 == count ) return false; @@ -651,7 +727,10 @@ bool LevelMutexInfo::IsLockedByAnotherThread( void ) const volatile { - LOKI_MUTEX_DEBUG_CODE( CheckFor::NoChangeOrThrow checker( this, &IsValid() ); (void)checker; ) + LOKI_MUTEX_DEBUG_CODE( + CheckFor::NoThrowOrChange checker( this, &LevelMutexInfo::IsValid ); + (void)checker; + ) if ( !IsLocked() ) return false; @@ -664,14 +743,31 @@ // ---------------------------------------------------------------------------- -void LevelMutexInfo::PostLock( void ) volatile +bool LevelMutexInfo::PostLockValidator( void ) const volatile { - LOKI_MUTEX_DEBUG_CODE( CheckFor::NoThrow checker( this, &IsValid() ); (void)checker; ) assert( 0 == m_count ); assert( nullptr == m_previous ); assert( this != s_currentMutex ); assert( !IsLockedByCurrentThread() ); + return true; +} + +// ---------------------------------------------------------------------------- + +void LevelMutexInfo::PostLock( void ) volatile +{ + LOKI_MUTEX_DEBUG_CODE( + CheckFor::NoThrow checker( this, &LevelMutexInfo::IsValid, + &LevelMutexInfo::PostLockValidator, &LevelMutexInfo::IsLockedByCurrentThreadImpl ); + (void)checker; + ) + + /** Of the three data members PostLock must modify, it should change the count + before changing the other two. The IsLocked function uses the count to see if + the mutex is locked, so changing this first stops other threads from trying to + lock the object before this thread can modify the other two data members. + */ m_count = 1; m_previous = s_currentMutex; s_currentMutex = this; @@ -679,14 +775,33 @@ // ---------------------------------------------------------------------------- -void LevelMutexInfo::PreUnlock( void ) volatile +bool LevelMutexInfo::PreUnlockValidator( void ) const volatile { - LOKI_MUTEX_DEBUG_CODE( CheckFor::NoThrow checker( this, &IsValid() ); (void)checker; ) assert( 1 == m_count ); assert( nullptr != s_currentMutex ); assert( this == s_currentMutex ); assert( IsLockedByCurrentThread() ); + return true; +} + +// ---------------------------------------------------------------------------- + +void LevelMutexInfo::PreUnlock( void ) volatile +{ + LOKI_MUTEX_DEBUG_CODE( + // This must use CheckFor::Invariants instead of CheckFor::NoThrow because the + // function gets called when MultiLock has to clean up after an exception. + CheckFor::Invariants checker( this, &LevelMutexInfo::IsValid, + &LevelMutexInfo::PreUnlockValidator, &LevelMutexInfo::IsNotLockedByCurrentThread ); + (void)checker; + ) + + /** Of the three data members PostLock must modify, it should change the count + after changing the other two. The IsLocked function uses the count to see if + the mutex is locked, so changing this last stops other threads from trying to + lock the object before this thread can modify the other two data members. + */ s_currentMutex = m_previous; m_previous = nullptr; m_count = 0; @@ -696,7 +811,10 @@ MutexErrors::Type LevelMutexInfo::PreLockCheck( bool forTryLock ) volatile { - LOKI_MUTEX_DEBUG_CODE( CheckFor::NoThrow checker( this, &IsValid() ); (void)checker; ) + LOKI_MUTEX_DEBUG_CODE( + CheckFor::NoThrow checker( this, &LevelMutexInfo::IsValid ); + (void)checker; + ) const unsigned int currentLevel = GetCurrentThreadsLevel(); if ( currentLevel < LevelMutexInfo::GetLevel() ) @@ -730,7 +848,10 @@ MutexErrors::Type LevelMutexInfo::PreUnlockCheck( void ) volatile { - LOKI_MUTEX_DEBUG_CODE( CheckFor::NoThrow checker( this, &IsValid() ); (void)checker; ) + LOKI_MUTEX_DEBUG_CODE( + CheckFor::NoThrow checker( this, &LevelMutexInfo::IsValid ); + (void)checker; + ) if ( 0 == m_count ) return MutexErrors::WasntLocked; @@ -803,9 +924,6 @@ switch ( result ) { case 0: -//#if defined( DEBUG_LOKI_LEVEL_MUTEX ) -// cout << __FUNCTION__ << '\t' << __LINE__ << endl; -//#endif return; case EBUSY: throw MutexException( "pthread mutex already initialized!", @@ -842,9 +960,6 @@ #if defined( _MSC_VER ) ::DeleteCriticalSection( &m_mutex ); #else -//#if defined( DEBUG_LOKI_LEVEL_MUTEX ) -// cout << __FUNCTION__ << '\t' << __LINE__ << endl; -//#endif ::pthread_mutex_destroy( &m_mutex ); #endif } @@ -868,9 +983,6 @@ switch ( result ) { case 0: -//#if defined( DEBUG_LOKI_LEVEL_MUTEX ) -// cout << __FUNCTION__ << '\t' << __LINE__ << endl; -//#endif break; default: case EINVAL: @@ -911,9 +1023,6 @@ switch ( result ) { case 0: -//#if defined( DEBUG_LOKI_LEVEL_MUTEX ) -// cout << __FUNCTION__ << '\t' << __LINE__ << endl; -//#endif return MutexErrors::Success; default: case EBUSY: @@ -943,9 +1052,6 @@ if ( EPERM == result ) throw MutexException( "current thread did not lock this pthread mutex!", GetLevel(), MutexErrors::NotLockedByThread ); -//#if defined( DEBUG_LOKI_LEVEL_MUTEX ) -// cout << __FUNCTION__ << '\t' << __LINE__ << endl; -//#endif #endif return MutexErrors::Success; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2011-11-07 23:55:04
|
Revision: 1175 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1175&view=rev Author: rich_sposato Date: 2011-11-07 23:54:58 +0000 (Mon, 07 Nov 2011) Log Message: ----------- Added Memento class to prove strong exception safety. Modified Paths: -------------- trunk/include/loki/LevelMutex.h Modified: trunk/include/loki/LevelMutex.h =================================================================== --- trunk/include/loki/LevelMutex.h 2011-11-07 23:35:28 UTC (rev 1174) +++ trunk/include/loki/LevelMutex.h 2011-11-07 23:54:58 UTC (rev 1175) @@ -144,8 +144,10 @@ { public: - /** Level for thread that has not locked any mutex. Maximum possible level - for a mutex is UnlockedLevel-1; No mutex may have a level of UnlockedLevel. + /** This is the default level for a thread that has not locked any mutex. The + maximum possible level for a mutex is UnlockedLevel-1, and I doubt any software + will ever have a call stack of more than 2^32-2 functions. No mutex may have a + level of UnlockedLevel. */ static const unsigned int UnlockedLevel = 0xFFFFFFFF; @@ -265,12 +267,35 @@ protected: + /// @class Memento Stores content of LevelMutexInfo so CheckFor can check invariants. + class Memento + { + public: + + explicit Memento( const volatile LevelMutexInfo & mutex ); + + bool operator == ( const volatile LevelMutexInfo & mutex ) const; + + private: + /// Level of this mutex. + const unsigned int m_level; + + /// How many times this mutex got locked. + const unsigned int m_count; + + /// Pointer to mutex locked before this one. + const volatile LevelMutexInfo * const m_previous; + + /// True if mutex was locked when Memento was constructed. + const bool m_locked; + }; + /** @note CheckFor performs validity checking in many functions to determine if the code violated any invariants, if any content changed, or if the function threw an exception. The checkers only get used in debug builds, and get optimized away in release builds. */ - typedef ::Loki::CheckFor< LevelMutexInfo > CheckFor; + typedef ::Loki::CheckFor< volatile LevelMutexInfo, Memento > CheckFor; /** @class MutexUndoer Undoes actions by MultiLock if an exception occurs. It keeps track of @@ -334,6 +359,17 @@ */ bool IsValid( void ) const volatile; + /** Returns true if no class invariant broken, otherwise asserts. This function + only gets called in debug builds. + */ + bool IsValid( void ) const; + + /// Returns true if all pre-conditions for PostLock function are valid. + bool PostLockValidator( void ) const volatile; + + /// Returns true if all pre-conditions for PreUnlock function are valid. + bool PreUnlockValidator( void ) const volatile; + private: /// Copy constructor is not implemented. @@ -359,6 +395,16 @@ /// Called only by MultiUnlock to unlock each particular mutex within a container. virtual MutexErrors::Type UnlockThis( void ) volatile = 0; + /** The actual implementation of IsLockedByCurrentThread. This does not do any + invariant checking because the functions which call it already have. + */ + bool IsLockedByCurrentThreadImpl( void ) const volatile; + + /** Does just the opposite of IsLockedByCurrentThread. Called as a post-condition + check by another function. + */ + bool IsNotLockedByCurrentThread( void ) const volatile; + /// Pointer to singly-linked list of mutexes locked by the current thread. static LOKI_THREAD_LOCAL volatile LevelMutexInfo * s_currentMutex; @@ -765,7 +811,7 @@ virtual MutexErrors::Type TryLock( void ) volatile { - LOKI_MUTEX_DEBUG_CODE( CheckFor::Invariants checker( this, &IsValid() ); (void)checker; ) + LOKI_MUTEX_DEBUG_CODE( CheckFor::NoChangeOnThrow checker( this, &IsValid ); (void)checker; ) MutexErrors::Type result = LevelMutexInfo::PreLockCheck( true ); if ( MutexErrors::Success == result ) @@ -786,7 +832,7 @@ virtual MutexErrors::Type Lock( void ) volatile { - LOKI_MUTEX_DEBUG_CODE( CheckFor::Invariants checker( this, &IsValid() ); (void)checker; ) + LOKI_MUTEX_DEBUG_CODE( CheckFor::NoChangeOnThrow checker( this, &IsValid ); (void)checker; ) MutexErrors::Type result = LevelMutexInfo::PreLockCheck( false ); if ( MutexErrors::Success == result ) @@ -805,7 +851,7 @@ virtual MutexErrors::Type Lock( unsigned int milliSeconds ) volatile { - LOKI_MUTEX_DEBUG_CODE( CheckFor::Invariants checker( this, &IsValid() ); (void)checker; ) + LOKI_MUTEX_DEBUG_CODE( CheckFor::NoChangeOnThrow checker( this, &IsValid ); (void)checker; ) MutexErrors::Type result = LevelMutexInfo::PreLockCheck( false ); if ( MutexErrors::Success == result ) @@ -840,7 +886,7 @@ virtual MutexErrors::Type Unlock( void ) volatile { - LOKI_MUTEX_DEBUG_CODE( CheckFor::Invariants checker( this, &IsValid() ); (void)checker; ) + LOKI_MUTEX_DEBUG_CODE( CheckFor::NoChangeOnThrow checker( this, &IsValid ); (void)checker; ) MutexErrors::Type result = LevelMutexInfo::PreUnlockCheck(); if ( MutexErrors::Success == result ) @@ -885,7 +931,7 @@ */ virtual MutexErrors::Type LockThis( void ) volatile { - LOKI_MUTEX_DEBUG_CODE( CheckFor::Invariants checker( this, &IsValid() ); (void)checker; ) + LOKI_MUTEX_DEBUG_CODE( CheckFor::NoChangeOnThrow checker( this, &IsValid ); (void)checker; ) assert( this != LevelMutexInfo::GetCurrentMutex() ); const MutexErrors::Type result = m_mutex.Lock(); @@ -905,7 +951,7 @@ */ virtual MutexErrors::Type LockThis( unsigned int milliSeconds ) volatile { - LOKI_MUTEX_DEBUG_CODE( CheckFor::Invariants checker( this, &IsValid() ); (void)checker; ) + LOKI_MUTEX_DEBUG_CODE( CheckFor::NoChangeOnThrow checker( this, &IsValid ); (void)checker; ) clock_t timeOut = clock() + milliSeconds; while ( clock() < timeOut ) @@ -930,7 +976,7 @@ */ virtual MutexErrors::Type UnlockThis( void ) volatile { - LOKI_MUTEX_DEBUG_CODE( CheckFor::Invariants checker( this, &IsValid() ); (void)checker; ) + LOKI_MUTEX_DEBUG_CODE( CheckFor::NoChangeOnThrow checker( this, &IsValid ); (void)checker; ) assert( NULL != LevelMutexInfo::GetCurrentMutex() ); if ( 1 < LevelMutexInfo::GetLockCount() ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2011-11-07 23:35:34
|
Revision: 1174 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1174&view=rev Author: rich_sposato Date: 2011-11-07 23:35:28 +0000 (Mon, 07 Nov 2011) Log Message: ----------- Added typedef for Validator function types. Modified Paths: -------------- trunk/include/loki/Checker.h Modified: trunk/include/loki/Checker.h =================================================================== --- trunk/include/loki/Checker.h 2011-11-07 23:31:36 UTC (rev 1173) +++ trunk/include/loki/Checker.h 2011-11-07 23:35:28 UTC (rev 1174) @@ -601,6 +601,8 @@ typedef ContractChecker< Host, CheckForNoThrow, Memento > NoThrow; typedef ContractChecker< Host, CheckForNoChange, Memento > NoChange; typedef ContractChecker< Host, CheckForNothing, Memento > Invariants; + + typedef bool ( Host:: * Validator )( void ) const; }; // ---------------------------------------------------------------------------- @@ -775,6 +777,7 @@ typedef StaticChecker< CheckStaticForNoThrow > NoThrow; typedef StaticChecker< CheckStaticForNothing > Invariants; + typedef bool ( * Validator )( void ); }; // ---------------------------------------------------------------------------- This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2011-11-07 23:31:42
|
Revision: 1173 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1173&view=rev Author: rich_sposato Date: 2011-11-07 23:31:36 +0000 (Mon, 07 Nov 2011) Log Message: ----------- Cosmetic changes. Modified Paths: -------------- trunk/test/LevelMutex/main.cpp Modified: trunk/test/LevelMutex/main.cpp =================================================================== --- trunk/test/LevelMutex/main.cpp 2011-11-04 00:54:46 UTC (rev 1172) +++ trunk/test/LevelMutex/main.cpp 2011-11-07 23:31:36 UTC (rev 1173) @@ -14,12 +14,7 @@ // //////////////////////////////////////////////////////////////////////////////// -// $Id$ - -// ---------------------------------------------------------------------------- - - #include "loki/LevelMutex.h" #include "MultiThreadTests.hpp" @@ -522,7 +517,6 @@ ExceptionMutex mutex2a( 2 ); mutex2a.GetMutexPolicy().SetTossPolicy( ExceptionTossingMutex::Never ); MutexErrors::Type result = MutexErrors::Success; - try { mutex1a.Lock(); @@ -557,6 +551,7 @@ ExceptionMutex mutex2d( 2 ); mutex2d.GetMutexPolicy().SetTossPolicy( ExceptionTossingMutex::Never ); LevelMutexInfo::MutexContainer mutexes; + try { mutexes.push_back( &mutex2a ); @@ -587,6 +582,7 @@ ExceptionMutex mutex3b( 3 ); mutex3b.GetMutexPolicy().SetTossPolicy( ExceptionTossingMutex::Never ); mutexes.clear(); + try { mutexes.push_back( &mutex3a ); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2011-11-04 00:54:53
|
Revision: 1172 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1172&view=rev Author: rich_sposato Date: 2011-11-04 00:54:46 +0000 (Fri, 04 Nov 2011) Log Message: ----------- Update cout strings to be more accurate. Added tests. Modified Paths: -------------- trunk/test/Checker/main.cpp Modified: trunk/test/Checker/main.cpp =================================================================== --- trunk/test/Checker/main.cpp 2011-11-04 00:53:49 UTC (rev 1171) +++ trunk/test/Checker/main.cpp 2011-11-04 00:54:46 UTC (rev 1172) @@ -70,7 +70,7 @@ unsigned int DoSomething( bool doThrow ) const; - void DoSomethingElse( void ) const; + void DoSomethingElse( unsigned int count, bool doThrow ); void AddCount( unsigned int count ); @@ -235,7 +235,7 @@ // This example shows how to use the equality checker. unsigned int Thingy::DoSomething( bool doThrow ) const { - CheckMementoFor::Equality checker( this, &Thingy::IsValid ); + CheckMementoFor::NoChange checker( this, &Thingy::IsValid ); (void)checker; if ( doThrow ) throw ::std::logic_error( "Test Exception." ); @@ -245,10 +245,16 @@ // ---------------------------------------------------------------------------- // This example shows how to use the no-change checker. -void Thingy::DoSomethingElse( void ) const +void Thingy::DoSomethingElse( unsigned int count, bool doThrow ) { - CheckMementoFor::NoChange checker( this, &Thingy::IsValid ); + CheckMementoFor::NoChangeOnThrow checker( this, &Thingy::IsValid ); (void)checker; + + IntBlock counts( m_counts ); + counts.push_back( count ); + if ( doThrow ) + throw ::std::logic_error( "Test Exception." ); + counts.swap( m_counts ); } // ---------------------------------------------------------------------------- @@ -270,7 +276,7 @@ // This function's checker cares about class invariants and both the pre- and // post-conditions, so it passes in pointers for all 3 validators. The pre- // and post-conditions are both about making sure the container is not empty. - CheckMementoFor::NoChangeOrThrow checker( this, &Thingy::IsValid, &Thingy::IsValidFull, &Thingy::IsValidFull ); + CheckMementoFor::NoThrowOrChange checker( this, &Thingy::IsValid, &Thingy::IsValidFull, &Thingy::IsValidFull ); if ( m_counts.size() <= index ) return 0; const unsigned int count = m_counts[ index ]; @@ -360,53 +366,89 @@ (void)argc; (void)argv; + cout << "These tests confirm the Checker exception policies work properly." << endl; + cout << "The tests will throw exceptions. If you see any assertions, the test failed." << endl; + try { cout << "Just before call to ThrowTest." << endl; ThrowTest(); cout << "Just after call to ThrowTest." << endl; + assert( false ); } catch ( const ::std::logic_error & ex ) { - cout << "Caught an exception! " << ex.what() << endl; + cout << "Caught a logic_error exception! " << ex.what() << endl; + assert( true ); } catch ( const ::std::exception & ex ) { - cout << "Caught an exception! " << ex.what() << endl; + cout << "Caught a standard exception! " << ex.what() << endl; + assert( false ); } catch ( ... ) { - cout << "Caught an exception!" << endl; + cout << "Caught an unknown exception!" << endl; + assert( false ); } unsigned int count = 0; try { - cout << "Running basic tests with Thingy." << endl; + cout << "Starting test of CheckFor::NoChange policy." << endl; // First do some tests on class member functions. Thingy t1( 1 ); t1.DoSomething( false ); + assert( true ); Thingy t2( 2 ); t2.DoSomething( true ); - cout << "Done with basic tests with Thingy." << endl; + assert( false ); } catch ( const ::std::logic_error & ex ) { cout << "Caught an exception! " << ex.what() << endl; + assert( true ); } catch ( const ::std::exception & ex ) { + cout << "Caught a standard exception! " << ex.what() << endl; + } + catch ( ... ) + { + cout << "Caught an unknown exception!" << endl; + } + cout << "Done testing CheckFor::NoChange policy." << endl; + + try + { + cout << "Starting test of CheckFor::NoChangeOnThrow policy." << endl; + Thingy t1( 1 ); + t1.DoSomethingElse( 3, false ); + Thingy t2( 2 ); + t2.DoSomethingElse( 5, true ); + assert( false ); + } + catch ( const ::std::logic_error & ex ) + { cout << "Caught an exception! " << ex.what() << endl; + assert( true ); } + catch ( const ::std::exception & ex ) + { + cout << "Caught a standard exception! " << ex.what() << endl; + assert( false ); + } catch ( ... ) { - cout << "Caught an exception!" << endl; + cout << "Caught an unknown exception!" << endl; + assert( false ); } + cout << "Finished test of CheckFor::NoChangeOnThrow policy." << endl; try { + cout << "Starting tests of CheckFor::Invariants and CheckFor::NoThrowOrChange policy." << endl; Thingy t1( 1 ); - cout << "Now running tests with Thingy counts." << endl; // These lines will exercise the functions with pre- and post-conditions. t1.AddCount( 11 ); t1.AddCount( 13 ); @@ -421,54 +463,64 @@ } catch ( const ::std::logic_error & ex ) { - cout << "Caught an exception! " << ex.what() << endl; + cout << "Caught a logic_error exception! " << ex.what() << endl; } catch ( const ::std::exception & ex ) { - cout << "Caught an exception! " << ex.what() << endl; + cout << "Caught a standard exception! " << ex.what() << endl; + assert( false ); } catch ( ... ) { - cout << "Caught an exception!" << endl; + cout << "Caught an unknown exception!" << endl; + assert( false ); } + cout << "Finished tests of CheckFor::Invariants and CheckFor::NoThrowOrChange policy." << endl; try { - cout << "Now run tests on static member functions" << endl; + cout << "Starting test of CheckStaticFor::Invariants policy." << endl; // Next do some tests with static member functions. Thingy::ChangeThat(); const unsigned int value = Thingy::GetThat(); assert( value != 0 ); - cout << "Done with tests on static member functions" << endl; + assert( true ); } catch ( const ::std::logic_error & ex ) { - cout << "Caught an exception! " << ex.what() << endl; + cout << "Caught a logic_error exception! " << ex.what() << endl; + assert( false ); } catch ( const ::std::exception & ex ) { - cout << "Caught an exception! " << ex.what() << endl; + cout << "Caught a standard exception! " << ex.what() << endl; + assert( false ); } catch ( ... ) { - cout << "Caught an exception!" << endl; + cout << "Caught an unknown exception!" << endl; + assert( false ); } + cout << "Finished test of CheckStaticFor::Invariants policy." << endl; try { - cout << "Now run test on a standalone function." << endl; + cout << "Starting test of CheckStaticFor::NoThrow policy." << endl; // Then do a test with a standalone function. DoSomething(); - cout << "Done with test on a standalone function." << endl; + assert( true ); } catch ( const ::std::exception & ex ) { - cout << "Caught an exception! " << ex.what() << endl; + cout << "Caught a standard exception! " << ex.what() << endl; + assert( false ); } catch ( ... ) { - cout << "Caught an exception!" << endl; + cout << "Caught an unknown exception!" << endl; + assert( false ); } + cout << "Finished test of CheckStaticFor::NoThrow policy." << endl; cout << "All done! If you see this line, and no assertions failed, then the test passed!" << endl; return 0; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2011-11-04 00:53:55
|
Revision: 1171 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1171&view=rev Author: rich_sposato Date: 2011-11-04 00:53:49 +0000 (Fri, 04 Nov 2011) Log Message: ----------- Changed names to be more descriptive. Updated comments. Modified Paths: -------------- trunk/include/loki/Checker.h Modified: trunk/include/loki/Checker.h =================================================================== --- trunk/include/loki/Checker.h 2011-10-24 18:07:46 UTC (rev 1170) +++ trunk/include/loki/Checker.h 2011-11-04 00:53:49 UTC (rev 1171) @@ -60,13 +60,13 @@ - and determining which exception safety level a function provides. @par Class & Data Invariants - ContractChecker and StaticChecker define invariants as "expressions that are - true for particular data". They call 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 + ContractChecker and StaticChecker define invariants as "conditions that are + true for particular objects". They call a function which returns true if all + conditions are valid, and returns false if any condition is invalid. This is + called the validator function, and the host class or function provides a + pointer to it. The validator may 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. @@ -92,22 +92,27 @@ @par Provided Exception Policies Loki provides several exception policies for use with ContractChecker. - - CheckForNoChangeOrThrow + - CheckForNoThrowOrChange - CheckForNoThrow + - CheckForNoChangeOnThrow - CheckForNoChange - - CheckForEquality - CheckForNothing Loki also provides these two policies for StaticChecker. - CheckStaticForNoThrow - CheckStaticForNothing - @par Writing Your Own Policies for ContractChecker - Loki provides several exception policies for ContractChecker. These policies - assert if an object changed or a function threw an exception. If you prefer - policies that log failures to a file, send an email, file a bug report, pop-up - a message box, notify your unit-test framework, or whatever else, you can - easily write your own policies. Please follow these guidelines when writing - your own policies: + @par Reasons to Write Your Own Policies for ContractChecker + Loki provides several exception policies for ContractChecker that assert if an + object changed or a function threw an exception. These are good reasons to + write your own policies: + - you want to log failures to a file, + - you want to create a bug report, + - you want to stop your unit-test framework, + - your classes don't have copy-constructors or equality operators, + - or whatever else. + + @par Guidelines for Writing Your Own Policies for ContractChecker + Please follow these guidelines when writing your own policies: - Each policy class must provide three public functions, a constructor, a destructor, and a Check function. - The destructor could be implied. (Not actually written, and provided by the compiler.) - The constructor and Check functions accept a pointer to const instance of the host class. @@ -238,15 +243,16 @@ // ---------------------------------------------------------------------------- -template < class Host, class Memento > class CheckForNoChange; +template < class Host, class Memento > class CheckForNoChangeOnThrow; -/** @class CheckForNoChange +/** @class CheckForNoChangeOnThrow @par Exception Safety Level: This exception-checking policy class for ContractChecker 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. + exception guarantee. Such functions provide transaction semantics - either the + action succeeds or the object rollsback to its previous state. @par Requirements: This policy requires hosts to provide both the copy-constructor and the @@ -254,11 +260,11 @@ */ template < class Host > -class CheckForNoChange< Host, void > +class CheckForNoChangeOnThrow< Host, void > { public: - inline explicit CheckForNoChange( const Host * host ) : + inline explicit CheckForNoChangeOnThrow( const Host * host ) : m_compare( *host ) {} inline bool Check( const Host * host ) const @@ -274,11 +280,11 @@ }; template < class Host, class Memento > -class CheckForNoChange +class CheckForNoChangeOnThrow { public: - inline explicit CheckForNoChange( const Host * host ) : + inline explicit CheckForNoChangeOnThrow( const Host * host ) : m_compare( *host ) {} inline bool Check( const Host * host ) const @@ -295,9 +301,9 @@ // ---------------------------------------------------------------------------- -template < class Host, class Memento > class CheckForNoChangeOrThrow; +template < class Host, class Memento > class CheckForNoThrowOrChange; -/** @class CheckForNoChangeOrThrow +/** @class CheckForNoThrowOrChange This policy comes in two forms - one uses a memento, and one does not. The memento form does not copy the host object, but stores info about the host in a memento for later comparison with the host. The other form copies the host @@ -315,11 +321,11 @@ */ template < class Host, class Memento > -class CheckForNoChangeOrThrow +class CheckForNoThrowOrChange { public: - inline explicit CheckForNoChangeOrThrow( const Host * host ) : + inline explicit CheckForNoThrowOrChange( const Host * host ) : m_compare( *host ) {} inline bool Check( const Host * host ) const @@ -336,11 +342,11 @@ }; template < class Host > -class CheckForNoChangeOrThrow< Host, void > +class CheckForNoThrowOrChange< Host, void > { public: - inline explicit CheckForNoChangeOrThrow( const Host * host ) : + inline explicit CheckForNoThrowOrChange( const Host * host ) : m_compare( *host ) {} inline bool Check( const Host * host ) const @@ -358,9 +364,9 @@ // ---------------------------------------------------------------------------- -template < class Host, class Memento > class CheckForEquality; +template < class Host, class Memento > class CheckForNoChange; -/** @class CheckForEquality +/** @class CheckForNoChange @par Exception Safety Level: This exception-checking policy class for ContractChecker asserts if a copy of @@ -378,11 +384,11 @@ */ template < class Host, class Memento > -class CheckForEquality +class CheckForNoChange { public: - inline explicit CheckForEquality( const Host * host ) : + inline explicit CheckForNoChange( const Host * host ) : m_compare( *host ) {} inline bool Check( const Host * host ) const @@ -397,11 +403,11 @@ }; template < class Host > -class CheckForEquality< Host, void > +class CheckForNoChange< Host, void > { public: - inline explicit CheckForEquality( const Host * host ) : + inline explicit CheckForNoChange( const Host * host ) : m_compare( *host ) {} inline bool Check( const Host * host ) const @@ -468,18 +474,18 @@ -# Add one of these lines at the top of various class member functions to construct a checker near the top of each public function. You may also pass in pointers to functions which check pre- and post-conditions. - - CheckFor::NoChangeOrThrow checker( this, &Host::IsValid ); + - CheckFor::NoThrowOrChange checker( this, &Host::IsValid ); + - CheckFor::NoChangeOnThrow checker( this, &Host::IsValid ); - CheckFor::NoThrow checker( this, &Host::IsValid ); - CheckFor::NoChange checker( this, &Host::IsValid ); - - CheckFor::Equality checker( this, &Host::IsValid ); - CheckFor::Invariants checker( this, &Host::IsValid ); -# Use these guidelines to decide which policy to use inside which function: - If the function never throws, then use the CheckForNoThrow policy. - - If the function never changes any data members, then use CheckForEquality + - If the function never changes any data members, then use CheckForNoChange 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. + CheckForNoChangeOnThrow policy. - Otherwise use the CheckInvariants policy. -# Recompile a debug version of your program, run the program and all the unit tests, and look for which assertions failed. @@ -569,10 +575,10 @@ /// Pointer to member function that checks Host object's invariants. Validator m_validator; - /// Pointer to member function that checks Host object's pre-conditions. + /// Pointer to member function that checks Host function's pre-conditions. Validator m_pre; - /// Pointer to member function that checks Host object's post-conditions. + /// Pointer to member function that checks Host function's post-conditions. Validator m_post; }; @@ -590,10 +596,10 @@ struct CheckFor { // These lines declare checkers for non-static functions in a host class. - typedef ContractChecker< Host, CheckForNoChangeOrThrow, Memento > NoChangeOrThrow; + typedef ContractChecker< Host, CheckForNoThrowOrChange, Memento > NoThrowOrChange; + typedef ContractChecker< Host, CheckForNoChangeOnThrow, Memento > NoChangeOnThrow; typedef ContractChecker< Host, CheckForNoThrow, Memento > NoThrow; typedef ContractChecker< Host, CheckForNoChange, Memento > NoChange; - typedef ContractChecker< Host, CheckForEquality, Memento > Equality; typedef ContractChecker< Host, CheckForNothing, Memento > Invariants; }; @@ -745,10 +751,10 @@ /// Pointer to member function that checks Host object's invariants. Validator m_validator; - /// Pointer to member function that checks Host object's pre-conditions. + /// Pointer to member function that checks Host function's pre-conditions. Validator m_pre; - /// Pointer to member function that checks Host object's post-conditions. + /// Pointer to member function that checks Host function's post-conditions. Validator m_post; }; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2011-10-24 18:07:52
|
Revision: 1170 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1170&view=rev Author: rich_sposato Date: 2011-10-24 18:07:46 +0000 (Mon, 24 Oct 2011) Log Message: ----------- Changed paths for project file. Modified Paths: -------------- trunk/test/Visitor/Visitor.cbp Modified: trunk/test/Visitor/Visitor.cbp =================================================================== --- trunk/test/Visitor/Visitor.cbp 2011-10-22 00:45:42 UTC (rev 1169) +++ trunk/test/Visitor/Visitor.cbp 2011-10-24 18:07:46 UTC (rev 1170) @@ -6,20 +6,20 @@ <Option compiler="cygwin" /> <Build> <Target title="Debug_GCC"> - <Option output="bin\Debug_GCC\Visitor" prefix_auto="1" extension_auto="1" /> - <Option object_output="obj\Debug_GCC\" /> + <Option output="bin/Debug_GCC/Visitor" prefix_auto="1" extension_auto="1" /> + <Option object_output="obj/Debug_GCC/" /> <Option type="1" /> <Option compiler="gcc" /> <Compiler> <Add option="-W" /> <Add option="-g" /> - <Add directory="..\..\include\loki" /> - <Add directory="..\..\include" /> + <Add directory="../../include/loki" /> + <Add directory="../../include" /> </Compiler> </Target> <Target title="Release_GCC"> - <Option output="bin\Release_GCC\Visitor" prefix_auto="1" extension_auto="1" /> - <Option object_output="obj\Release_GCC\" /> + <Option output="bin/Release_GCC/Visitor" prefix_auto="1" extension_auto="1" /> + <Option object_output="obj/Release_GCC/" /> <Option type="1" /> <Option compiler="gcc" /> <Compiler> @@ -27,25 +27,25 @@ <Add option="-Os" /> <Add option="-O3" /> <Add option="-W" /> - <Add directory="..\..\include\loki" /> - <Add directory="..\..\include" /> + <Add directory="../../include/loki" /> + <Add directory="../../include" /> </Compiler> </Target> <Target title="Debug_Cygwin"> - <Option output="bin\Debug_Cygwin\Visitor" prefix_auto="1" extension_auto="1" /> - <Option object_output="obj\Debug_Cygwin\" /> + <Option output="bin/Debug_Cygwin/Visitor" prefix_auto="1" extension_auto="1" /> + <Option object_output="obj/Debug_Cygwin/" /> <Option type="1" /> <Option compiler="cygwin" /> <Compiler> <Add option="-W" /> <Add option="-g" /> - <Add directory="..\..\include\loki" /> - <Add directory="..\..\include" /> + <Add directory="../../include/loki" /> + <Add directory="../../include" /> </Compiler> </Target> <Target title="Release_Cygwin"> - <Option output="bin\Release_Cygwin\Visitor" prefix_auto="1" extension_auto="1" /> - <Option object_output="obj\Release_Cygwin\" /> + <Option output="bin/Release_Cygwin/Visitor" prefix_auto="1" extension_auto="1" /> + <Option object_output="obj/Release_Cygwin/" /> <Option type="1" /> <Option compiler="cygwin" /> <Compiler> @@ -53,8 +53,8 @@ <Add option="-Os" /> <Add option="-O3" /> <Add option="-W" /> - <Add directory="..\..\include\loki" /> - <Add directory="..\..\include" /> + <Add directory="../../include/loki" /> + <Add directory="../../include" /> </Compiler> </Target> </Build> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2011-10-22 00:45:48
|
Revision: 1169 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1169&view=rev Author: rich_sposato Date: 2011-10-22 00:45:42 +0000 (Sat, 22 Oct 2011) Log Message: ----------- Added path to pthread library. Modified Paths: -------------- trunk/test/SafeFormat/SafeFormat.cbp Modified: trunk/test/SafeFormat/SafeFormat.cbp =================================================================== --- trunk/test/SafeFormat/SafeFormat.cbp 2011-10-22 00:30:16 UTC (rev 1168) +++ trunk/test/SafeFormat/SafeFormat.cbp 2011-10-22 00:45:42 UTC (rev 1169) @@ -36,6 +36,7 @@ </Compiler> <Linker> <Add library="../../lib/GCC/Loki.a" /> + <Add library="/usr/lib/libpthread.so" /> </Linker> </Target> <Target title="Debug_Cygwin"> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2011-10-22 00:30:23
|
Revision: 1168 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1168&view=rev Author: rich_sposato Date: 2011-10-22 00:30:16 +0000 (Sat, 22 Oct 2011) Log Message: ----------- Uses common path to pthread library. Modified Paths: -------------- trunk/test/LevelMutex/LevelMutex.cbp Modified: trunk/test/LevelMutex/LevelMutex.cbp =================================================================== --- trunk/test/LevelMutex/LevelMutex.cbp 2011-10-22 00:29:15 UTC (rev 1167) +++ trunk/test/LevelMutex/LevelMutex.cbp 2011-10-22 00:30:16 UTC (rev 1168) @@ -11,14 +11,14 @@ <Option type="1" /> <Option compiler="gcc" /> <Compiler> + <Add option="-g" /> <Add option="-W" /> - <Add option="-g" /> <Add directory="../../include" /> <Add directory="../../include/loki" /> </Compiler> <Linker> <Add library="../../lib/GCC/Loki_D.a" /> - <Add library="../../../PThreads/lib/pthreadVC2.lib" /> + <Add library="/usr/lib/libpthread.so" /> </Linker> </Target> <Target title="Release_GCC"> @@ -36,7 +36,7 @@ </Compiler> <Linker> <Add library="../../lib/GCC/Loki.a" /> - <Add library="../../../PThreads/lib/pthreadVC2.lib" /> + <Add library="/usr/lib/libpthread.so" /> </Linker> </Target> <Target title="Debug_Cygwin"> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ric...@us...> - 2011-10-22 00:29:22
|
Revision: 1167 http://loki-lib.svn.sourceforge.net/loki-lib/?rev=1167&view=rev Author: rich_sposato Date: 2011-10-22 00:29:15 +0000 (Sat, 22 Oct 2011) Log Message: ----------- Moved constructions of ThreadPool into blocks within functions. Added cout lines to say when tests start and finish. Modified Paths: -------------- trunk/test/LevelMutex/MultiThreadTests.cpp Modified: trunk/test/LevelMutex/MultiThreadTests.cpp =================================================================== --- trunk/test/LevelMutex/MultiThreadTests.cpp 2011-10-22 00:26:21 UTC (rev 1166) +++ trunk/test/LevelMutex/MultiThreadTests.cpp 2011-10-22 00:29:15 UTC (rev 1167) @@ -4,9 +4,9 @@ // Copyright (c) 2008, 2009 Richard 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 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 @@ -22,11 +22,10 @@ #include "MultiThreadTests.hpp" #include <assert.h> -#include <process.h> #include <stdlib.h> #include <time.h> -#include <SafeFormat.h> +#include <loki/SafeFormat.h> #include "ThreadPool.hpp" #include "Thing.hpp" @@ -239,29 +238,40 @@ void MultiThreadSimpleTest( void ) { + cout << "Starting MultiThreadSimpleTest." << endl; + + char ender; Thing::Init( 0 ); const unsigned int threadCount = 5; - ThreadPool pool( threadCount ); - cout << endl << "Doing thread-locked print test. This test should pass. and not deadlock" << endl; - ::system( "pause" ); - for ( unsigned int ii = 0; ii < threadCount; ++ii ) { - void * p = reinterpret_cast< void * >( ii ); - pool.Start( PrintSafeThread, p ); + ThreadPool pool( threadCount ); + cout << "Doing thread-locked print test. This test should pass and not deadlock" << endl; + cout << "Press <Enter> key to start test. "; + cin.get( ender ); + for ( unsigned int ii = 0; ii < threadCount; ++ii ) + { + void * p = reinterpret_cast< void * >( ii ); + pool.Start( PrintSafeThread, p ); + } + pool.JoinAll(); } - pool.JoinAll(); - cout << endl << "Doing thread-unsafe print test. This test may fail." << endl; - ::system( "pause" ); - for ( unsigned int ii = 0; ii < threadCount; ++ii ) { - void * p = reinterpret_cast< void * >( ii ); - pool.Start( PrintUnsafeThread, p ); + ThreadPool pool( threadCount ); + cout << endl << "Doing thread-unsafe print test. This test may fail, but not deadlock." << endl; + cout << "Press <Enter> key to start test. "; + cin.get( ender ); + for ( unsigned int ii = 0; ii < threadCount; ++ii ) + { + void * p = reinterpret_cast< void * >( ii ); + pool.Start( PrintUnsafeThread, p ); + } + pool.JoinAll(); } - pool.JoinAll(); Thing::Destroy(); + cout << "Finished MultiThreadSimpleTest." << endl; } // ---------------------------------------------------------------------------- @@ -289,6 +299,7 @@ } const unsigned int gotValue = thing.GetValue(); assert( gotValue != value ); + (void)gotValue; } assert( mutex.IsLockedByAnotherThread() ); @@ -299,13 +310,13 @@ void MultiThreadTryLockTest( void ) { + cout << "Starting MultiThreadTryLockTest." << endl; + + char ender; static const unsigned int threadCount = 3; Thing::Init( 0 ); volatile Thing & thing = Thing::GetIt(); volatile SleepMutex & mutex = thing.GetMutex(); - - cout << endl << "Doing multi-threaded TryLock test. This test should not deadlock." << endl; - ::system( "pause" ); // First step is to lock the mutex in the main thread so no child thread // can ever lock it, change the value, or anything like that. MutexErrors::Type result = mutex.Lock(); @@ -313,15 +324,22 @@ bool okay = mutex.IsLockedByCurrentThread(); assert( okay ); thing.SetValue( threadCount ); - ThreadPool pool( threadCount ); - for ( unsigned int ii = 0; ii < threadCount; ++ii ) + { - void * p = reinterpret_cast< void * >( ii ); - pool.Start( TryLockThread, p ); + ThreadPool pool( threadCount ); + cout << endl << "Doing multi-threaded TryLock test. This test should not deadlock." << endl; + cout << "Press <Enter> key to start test. "; + cin.get( ender ); + for ( unsigned int ii = 0; ii < threadCount; ++ii ) + { + void * p = reinterpret_cast< void * >( ii ); + pool.Start( TryLockThread, p ); + } + pool.JoinAll(); + const unsigned int value = thing.GetValue(); + assert( value == threadCount ); } - pool.JoinAll(); - const unsigned int value = thing.GetValue(); - assert( value == threadCount ); + result = mutex.Unlock(); assert( MutexErrors::Success == result ); okay = !mutex.IsLockedByCurrentThread(); @@ -330,39 +348,53 @@ assert( okay ); Thing::Destroy(); + + cout << "Finished MultiThreadTryLockTest." << endl; } // ---------------------------------------------------------------------------- void MultiThreadReentrantTest( void ) { + cout << "Starting MultiThreadReentrantTest." << endl; + + char ender; Thing::Init( 0 ); const unsigned int threadCount = 8; TestResults::Create( threadCount ); - ThreadPool pool( threadCount ); - cout << endl << "Doing thread-safe value test. This test should pass and not deadlock." << endl; - ::system( "pause" ); - for ( unsigned int ii = 0; ii < threadCount; ++ii ) { - void * p = reinterpret_cast< void * >( ii ); - pool.Start( ValueSafeThread, p ); + ThreadPool pool( threadCount ); + cout << endl << "Doing thread-safe value test. This test should pass and not deadlock." << endl; + cout << "Press <Enter> key to start test. "; + cin.get( ender ); + for ( unsigned int ii = 0; ii < threadCount; ++ii ) + { + void * p = reinterpret_cast< void * >( ii ); + pool.Start( ValueSafeThread, p ); + } + pool.JoinAll(); + TestResults::GetIt()->OutputResults(); } - pool.JoinAll(); - TestResults::GetIt()->OutputResults(); - cout << endl << "Doing thread-unsafe value test. This test may fail." << endl; - ::system( "pause" ); - for ( unsigned int ii = 0; ii < threadCount; ++ii ) { - void * p = reinterpret_cast< void * >( ii ); - pool.Start( ValueUnsafeThread, p ); + ThreadPool pool( threadCount ); + cout << endl << "Doing thread-unsafe value test. This test may fail." << endl; + cout << "Press <Enter> key to start test. "; + cin.get( ender ); + for ( unsigned int ii = 0; ii < threadCount; ++ii ) + { + void * p = reinterpret_cast< void * >( ii ); + pool.Start( ValueUnsafeThread, p ); + } + pool.JoinAll(); + TestResults::GetIt()->OutputResults(); } - pool.JoinAll(); - TestResults::GetIt()->OutputResults(); TestResults::Destroy(); Thing::Destroy(); + + cout << "Finished MultiThreadReentrantTest." << endl; } // ---------------------------------------------------------------------------- @@ -567,6 +599,7 @@ bool okay = locker.Unlock(); assert( okay ); + (void)okay; ::GoToSleep( 2 ); } } @@ -646,34 +679,46 @@ void MultiThreadMultiLockTest( void ) { + cout << "Starting MultiThreadMultiLockTest." << endl; + + char ender; Thing::MakePool( thingCount ); const unsigned int threadCount = 8; TestResults::Create( threadCount ); - ThreadPool pool( threadCount ); - cout << endl << "Doing thread-safe multi-lock test. This test should pass and not deadlock." << endl; - ::system( "pause" ); - for ( unsigned int ii = 0; ii < threadCount; ++ii ) { - void * p = reinterpret_cast< void * >( ii ); - pool.Start( MultiLockSafeThread, p ); + ThreadPool pool( threadCount ); + cout << endl << "Doing thread-safe multi-lock test. This test should pass and not deadlock." << endl; + cout << "Press <Enter> key to start test. "; + cin.get( ender ); + for ( unsigned int ii = 0; ii < threadCount; ++ii ) + { + void * p = reinterpret_cast< void * >( ii ); + pool.Start( MultiLockSafeThread, p ); + } + pool.JoinAll(); + TestResults::GetIt()->OutputResults(); } - pool.JoinAll(); - TestResults::GetIt()->OutputResults(); - cout << endl << "Doing thread-unsafe multi-lock test. This test may fail." << endl; - TestResults::GetIt()->Reset( threadCount ); - ::system( "pause" ); - for ( unsigned int ii = 0; ii < threadCount; ++ii ) { - void * p = reinterpret_cast< void * >( ii ); - pool.Start( MultiLockUnsafeThread, p ); + ThreadPool pool( threadCount ); + cout << endl << "Doing thread-unsafe multi-lock test. This test may fail." << endl; + TestResults::GetIt()->Reset( threadCount ); + cout << "Press <Enter> key to start test. "; + cin.get( ender ); + for ( unsigned int ii = 0; ii < threadCount; ++ii ) + { + void * p = reinterpret_cast< void * >( ii ); + pool.Start( MultiLockUnsafeThread, p ); + } + pool.JoinAll(); + TestResults::GetIt()->OutputResults(); } - pool.JoinAll(); - TestResults::GetIt()->OutputResults(); TestResults::Destroy(); Thing::DestroyPool(); + + cout << "Finished MultiThreadMultiLockTest." << endl; } // ---------------------------------------------------------------------------- @@ -770,7 +815,7 @@ place += ::rand() % 3; if ( thingCount <= place ) break; - thing = thing = const_cast< Thing * >( Thing::GetFromPool( place ) ); + thing = const_cast< Thing * >( Thing::GetFromPool( place ) ); assert( nullptr != thing ); pool.push_back( thing ); } @@ -808,34 +853,46 @@ void MultiThreadRandomMultiLockTest( void ) { + cout << "Starting MultiThreadRandomMultiLockTest." << endl; + + char ender; Thing::MakePool( thingCount ); const unsigned int threadCount = 8; TestResults::Create( threadCount ); - ThreadPool pool( threadCount ); - cout << endl << "Doing thread-safe random multi-lock test. This test should pass and not deadlock." << endl; - ::system( "pause" ); - for ( unsigned int ii = 0; ii < threadCount; ++ii ) { - void * p = reinterpret_cast< void * >( ii ); - pool.Start( MultiLockRandomSafeThread, p ); + ThreadPool pool( threadCount ); + cout << endl << "Doing thread-safe random multi-lock test. This test should pass and not deadlock." << endl; + cout << "Press <Enter> key to start test. "; + cin.get( ender ); + for ( unsigned int ii = 0; ii < threadCount; ++ii ) + { + void * p = reinterpret_cast< void * >( ii ); + pool.Start( MultiLockRandomSafeThread, p ); + } + pool.JoinAll(); + TestResults::GetIt()->OutputResults(); } - pool.JoinAll(); - TestResults::GetIt()->OutputResults(); - cout << endl << "Doing thread-unsafe random multi-lock test. This test may fail." << endl; - TestResults::GetIt()->Reset( threadCount ); - ::system( "pause" ); - for ( unsigned int ii = 0; ii < threadCount; ++ii ) { - void * p = reinterpret_cast< void * >( ii ); - pool.Start( MultiLockRandomUnsafeThread, p ); + ThreadPool pool( threadCount ); + cout << endl << "Doing thread-unsafe random multi-lock test. This test may fail." << endl; + TestResults::GetIt()->Reset( threadCount ); + cout << "Press <Enter> key to start test. "; + cin.get( ender ); + for ( unsigned int ii = 0; ii < threadCount; ++ii ) + { + void * p = reinterpret_cast< void * >( ii ); + pool.Start( MultiLockRandomUnsafeThread, p ); + } + pool.JoinAll(); + TestResults::GetIt()->OutputResults(); } - pool.JoinAll(); - TestResults::GetIt()->OutputResults(); TestResults::Destroy(); Thing::DestroyPool(); + + cout << "Finished MultiThreadRandomMultiLockTest." << endl; } // ---------------------------------------------------------------------------- @@ -936,34 +993,46 @@ void MultiThreadHierarchySingleLockTest( void ) { + cout << "Starting MultiThreadHierarchySingleLockTest." << endl; + + char ender; LevelThing::MakePool( thingCount ); const unsigned int threadCount = 8; TestResults::Create( threadCount ); - ThreadPool pool( threadCount ); - cout << endl << "Doing thread-safe hierarchy test. This test should pass and not deadlock." << endl; - ::system( "pause" ); - for ( unsigned int ii = 0; ii < threadCount; ++ii ) { - void * p = reinterpret_cast< void * >( ii ); - pool.Start( SafeHierarchyTest, p ); + ThreadPool pool( threadCount ); + cout << endl << "Doing thread-safe hierarchy test. This test should pass and not deadlock." << endl; + cout << "Press <Enter> key to start test. "; + cin.get( ender ); + for ( unsigned int ii = 0; ii < threadCount; ++ii ) + { + void * p = reinterpret_cast< void * >( ii ); + pool.Start( SafeHierarchyTest, p ); + } + pool.JoinAll(); + TestResults::GetIt()->OutputResults(); } - pool.JoinAll(); - TestResults::GetIt()->OutputResults(); - cout << endl << "Doing thread-unsafe hierarchy test. This test may fail." << endl; - ::system( "pause" ); - TestResults::GetIt()->Reset( threadCount ); - for ( unsigned int ii = 0; ii < threadCount; ++ii ) { - void * p = reinterpret_cast< void * >( ii ); - pool.Start( UnsafeHierarchyTest, p ); + ThreadPool pool( threadCount ); + cout << endl << "Doing thread-unsafe hierarchy test. This test may fail." << endl; + cout << "Press <Enter> key to start test. "; + cin.get( ender ); + TestResults::GetIt()->Reset( threadCount ); + for ( unsigned int ii = 0; ii < threadCount; ++ii ) + { + void * p = reinterpret_cast< void * >( ii ); + pool.Start( UnsafeHierarchyTest, p ); + } + pool.JoinAll(); + TestResults::GetIt()->OutputResults(); } - pool.JoinAll(); - TestResults::GetIt()->OutputResults(); TestResults::Destroy(); LevelThing::DestroyPool(); + + cout << "Finished MultiThreadHierarchySingleLockTest." << endl; } // ---------------------------------------------------------------------------- @@ -1064,35 +1133,46 @@ void MultiThreadHierarchyMultiLockTest( void ) { + cout << "Starting MultiThreadHierarchyMultiLockTest." << endl; + char ender; MultiLevelPool::MakePool( 10, thingCount ); const unsigned int threadCount = 8; TestResults::Create( threadCount ); - ThreadPool pool( threadCount ); - cout << endl << "Doing thread-safe multilock hierarchy test. This test should pass and not deadlock." << endl; - ::system( "pause" ); - for ( unsigned int ii = 0; ii < threadCount; ++ii ) { - void * p = reinterpret_cast< void * >( ii ); - pool.Start( SafeHierarchyMultiLockTest, p ); + ThreadPool pool( threadCount ); + cout << endl << "Doing thread-safe multilock hierarchy test. This test should pass and not deadlock." << endl; + cout << "Press <Enter> key to start test. "; + cin.get( ender ); + for ( unsigned int ii = 0; ii < threadCount; ++ii ) + { + void * p = reinterpret_cast< void * >( ii ); + pool.Start( SafeHierarchyMultiLockTest, p ); + } + pool.JoinAll(); + TestResults::GetIt()->OutputResults(); } - pool.JoinAll(); - TestResults::GetIt()->OutputResults(); - cout << endl << "Doing thread-unsafe multilock hierarchy test. This test may fail." << endl; - ::system( "pause" ); - TestResults::GetIt()->Reset( threadCount ); - for ( unsigned int ii = 0; ii < threadCount; ++ii ) { - void * p = reinterpret_cast< void * >( ii ); - pool.Start( UnsafeHierarchyMultiLockTest, p ); + ThreadPool pool( threadCount ); + cout << endl << "Doing thread-unsafe multilock hierarchy test. This test may fail." << endl; + cout << "Press <Enter> key to start test. "; + cin.get( ender ); + TestResults::GetIt()->Reset( threadCount ); + for ( unsigned int ii = 0; ii < threadCount; ++ii ) + { + void * p = reinterpret_cast< void * >( ii ); + pool.Start( UnsafeHierarchyMultiLockTest, p ); + } + pool.JoinAll(); + TestResults::GetIt()->OutputResults(); } - pool.JoinAll(); - TestResults::GetIt()->OutputResults(); TestResults::Destroy(); MultiLevelPool::DestroyPool(); + + cout << "Finished MultiThreadHierarchyMultiLockTest." << endl; } // ---------------------------------------------------------------------------- This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |