00001 #ifndef guard_range_checking_hpp 00002 #define guard_range_checking_hpp 00003 /** 00004 * @file 00005 * 00006 * @brief Details can be found in the documentation for 00007 * TAO::details::generic_sequence 00008 * 00009 * $Id: Range_Checking_T.h 72216 2006-04-20 12:40:50Z jwillemsen $ 00010 * 00011 * @author Carlos O'Ryan 00012 */ 00013 00014 #include "tao/Basic_Types.h" 00015 00016 TAO_BEGIN_VERSIONED_NAMESPACE_DECL 00017 00018 namespace TAO 00019 { 00020 namespace details 00021 { 00022 00023 /** 00024 * @struct range_checking 00025 * 00026 * @brief Configurable traits to tradeoff safety vs. performance in 00027 * the implementation of TAO sequences. 00028 * 00029 * The CORBA specification grants certain latitude to implementors by 00030 * not defining the behavior of sequences under certain conditions. 00031 * Probably the most clear example is the operator[] access, where the 00032 * application <b>must</b> set the length to a high enough value 00033 * before using the operator[]. 00034 * 00035 * Implementors that cater to high-performance applications tend to 00036 * exploit this latitude to the extreme, basically reasoning that 00037 * correct applications will behave normally, while incorrect 00038 * applications will crash, but those crashes will be detected during 00039 * development/testing. 00040 * 00041 * Realizing that this may be a bad tradeoff some implementors offer 00042 * compile-time hooks to control the behavior of sequences when used 00043 * improperly, some implementors may go as far as using run-time 00044 * hooks. 00045 * 00046 * The implementation of sequences calls the following template class 00047 * in points where the application may trigger undefined behavior. 00048 * The application developer can use partial (or full) template 00049 * specialization to introduce her own code at these critical points. 00050 * 00051 * Some examples may help, suppose you want to change your application 00052 * so for all sequence types the operator[] raises an exception if the 00053 * index is out of range. Then you would provide the following 00054 * (partial) template specialization: 00055 * 00056 * <PRE> 00057 * template<typename T> 00058 * struct range_checking<T,true> { 00059 * void check(CORBA::ULong index, CORBA::ULong length) { 00060 * if (index < length) 00061 * return; 00062 * throw std::range_error("CORBA sequence range error"); 00063 * }; 00064 * ... 00065 * .. 00066 * }; 00067 * </PRE> 00068 * 00069 * This specialization must be introduced before any sequence code is 00070 * seen, therefore, the application would also need to define the 00071 * following macro in their $ACE_ROOT/ace/config.h file: 00072 * 00073 * - #define TAO_USER_DEFINED_SEQUENCE_SAFETY_TRAITS_INCLUDE "<filename here>" 00074 * 00075 * Likewise, if the application only wanted to check the range for a 00076 * special type, say some structure MyStruct, then they would provide 00077 * a full specialization. Just for giggles, we will also introduce 00078 * run-time controls to this example: 00079 * 00080 * <PRE> 00081 * template<> 00082 * struct safety_traits<tao::details::value_traits<MyStruct>,true> { 00083 * bool enable_range_checking; 00084 * void check_range(CORBA::ULong index, CORBA::ULong length) { 00085 * if (!enable_range_checking || index < length) 00086 * return; 00087 * throw std::range_error("CORBA sequence range error"); 00088 * }; 00089 * ... 00090 * .. 00091 * }; 00092 * </PRE> 00093 * 00094 * 00095 * 00096 * @todo There is no control on a per-sequence type basis, only on a 00097 * per-underlying type basis, for example, the following two IDL 00098 * sequences would get the same behavior: 00099 * // IDL 00100 * typedef sequence<MyStruct> MyStructSequence; 00101 * typedef sequence<MyStruct> MyStructList; 00102 * 00103 * @todo There is no way to control behavior on a per-sequence basis, 00104 * i.e. to have some sequences of longs checked while others are 00105 * not. This is easy to fix, simply: 00106 * - make all members of safety_traits non-static 00107 * - have each sequence contain their own instance of 00108 * safety_traits 00109 * - grant users read/write access to the safety_traits of each 00110 * sequence 00111 * but there are footprint consequences to that approach. Until 00112 * there is more demand to justify the cost, I will not 00113 * implement such a change. 00114 */ 00115 template<typename T, bool dummy> 00116 struct range_checking 00117 { 00118 typedef T value_type; 00119 00120 inline static void check( 00121 CORBA::ULong /* index */, 00122 CORBA::ULong /* length */, 00123 CORBA::ULong /* maximum */, 00124 char const * /* function_name */) 00125 { 00126 // Applications and tests can specialize this function to define 00127 // their own behavior 00128 } 00129 00130 inline static void check_length( 00131 CORBA::ULong & /* new_length */, 00132 CORBA::ULong /* maximum */) 00133 { 00134 /* 00135 if (maximum < new_length) 00136 new_length = maximum; 00137 */ 00138 } 00139 }; 00140 00141 } // namespace details 00142 } // namespace TAO 00143 00144 TAO_END_VERSIONED_NAMESPACE_DECL 00145 00146 #if defined(TAO_USER_DEFINED_SEQUENCE_RANGE_CHECKING_INCLUDE) 00147 # include TAO_USER_DEFINED_SEQUENCE_RANGE_CHECKING_INCLUDE 00148 #endif // TAO_USER_DEFINED_SEQUENCE_RANGE_CHECKING_INCLUDE 00149 00150 #endif // guard_range_checking_hpp