Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

148 lines
3.8 KiB

  1. /*
  2. *
  3. *
  4. * _INVAR.H
  5. *
  6. * Purpose:
  7. * Template class designed to call parameterized object's Invariant().
  8. *
  9. * Overview (see also, usage):
  10. * 1) declare and define a public const function BOOL Invariant( void ) in your class, with #ifdef DEBUG.
  11. * 2) in the source: #define DEBUG_CLASSNAME to be the name of the class you're debugging.
  12. * 3) followed by #include "_invar.h"
  13. * 4) For every method you wish to check Invariants,
  14. * insert the _TEST_INVARIANT_ macro once, usually at the beginning of a routine.
  15. * OPTIONAL: You may optionally use the _TEST_INVARIANT_ON (x) to call x's Invariant directly.
  16. *
  17. * Notes:
  18. * Invariants are designed to be called at the beginning and upon exit of a routine,
  19. * testing the consistent properties of an object which remain invariant--always the same.
  20. *
  21. * Functions may temporarily make an object inconsistent during their execution.
  22. * A generalized invariant test should not be called during these inconsistent times;
  23. * if there is a need for a function, which checks invariants, to be called during
  24. * an inconsistent object state, a solution will need to be designed--the current design
  25. * does not facilitate this.
  26. *
  27. * Because it is entirely possible for an Invariant() function to recurse on itself
  28. * causing a stack overflow, the template explicitly prevents this from happening.
  29. * The template also prevents invariant-checking during the processing of Assert(),
  30. * preventing another type of recursion.
  31. *
  32. * Currently Invariant() returns a BOOL, as I think this allows for it to be called
  33. * from the QuickWatch window under VC++2.0. TRUE indicates that the invariant executed
  34. * normally.
  35. *
  36. * Usage:
  37. * -the _invariant.h header should only be included in source files. An error will occur
  38. * if included in another header file. This is to prevent multiple #define DEBUG_CLASSNAME.
  39. * -Typical #include into a source file looks like this:
  40. #define DEBUG_CLASSNAME ClassName
  41. #include "_invar.h"
  42. * -Typical definition of a class' Invariant() method looks like this:
  43. #ifdef DEBUG
  44. public:
  45. BOOL Invariant( void ) const;
  46. protected:
  47. #endif // DEBUG
  48. * -Typical declaration of Invariant() looks like this:
  49. #ifdef DEBUG
  50. BOOL
  51. ClassName::Invariant( void ) const
  52. {
  53. static LONG numTests = 0;
  54. numTests++; // how many times we've been called.
  55. // do mega-assert checking here.
  56. return TRUE;
  57. }
  58. #endif // DEBUG
  59. *
  60. *
  61. *
  62. *
  63. * Author:
  64. * Jon Matousek (jonmat) 5/04/1995
  65. *
  66. * Any problems? Please let me know.
  67. */
  68. #ifndef _INVARIANT_H
  69. #define _INVARIANT_H
  70. #ifndef DEBUG_CLASSNAME
  71. prior to including _invariant.h file, you must define DEBUG_CLASSNAME
  72. to be the name of the class for which you are making Invariant() calls.
  73. #endif
  74. #ifdef DEBUG
  75. template < class T >
  76. class InvariantDebug
  77. {
  78. public:
  79. InvariantDebug ( const T & t) : _t(t)
  80. {
  81. static volatile BOOL fRecurse = FALSE;
  82. if ( fRecurse ) return; /* Don't allow recursion.*/
  83. fRecurse = TRUE;
  84. _t.Invariant();
  85. fRecurse = FALSE;
  86. }
  87. ~InvariantDebug ()
  88. {
  89. static volatile BOOL fRecurse = FALSE;
  90. if ( fRecurse ) return; /* Don't allow recursion.*/
  91. fRecurse = TRUE;
  92. _t.Invariant();
  93. fRecurse = FALSE;
  94. }
  95. private:
  96. const T &_t;
  97. };
  98. typedef InvariantDebug<DEBUG_CLASSNAME> DoInvariant;
  99. #define _TEST_INVARIANT_ DoInvariant __invariant_tester( *this );
  100. #define _TEST_INVARIANT_ON(x) \
  101. {\
  102. static volatile BOOL fRecurse = FALSE;\
  103. if (FALSE == fRecurse )\
  104. {\
  105. fRecurse = TRUE;\
  106. (x).Invariant();\
  107. fRecurse = FALSE;\
  108. }\
  109. }
  110. #else // DEBUG
  111. #define _TEST_INVARIANT_
  112. #define _TEST_INVARIANT_ON(x)
  113. #endif // DEBUG
  114. // code that should be at the start and end of all Invariant() methods.
  115. #else // INVARIANT_H
  116. This file should only be included once per source file. jonmat
  117. #endif // INVARIANT_H