summaryrefslogtreecommitdiff
path: root/TAO/tao/Range_Checking_T.h
blob: f5e461ef09f8880a8d26fab432568a907a74bc57 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#ifndef guard_range_checking_hpp
#define guard_range_checking_hpp
/**
 * @file
 *
 * @brief Details can be found in the documentation for
 * TAO::details::generic_sequence
 *
 * $Id$
 *
 * @author Carlos O'Ryan
 */

#include "tao/Basic_Types.h"

TAO_BEGIN_VERSIONED_NAMESPACE_DECL

namespace TAO
{
namespace details
{

/**
 * @struct range_checking
 *
 * @brief Configurable traits to tradeoff safety vs. performance in
 *        the implementation of TAO sequences.
 *
 * The CORBA specification grants certain latitude to implementors by
 * not defining the behavior of sequences under certain conditions.
 * Probably the most clear example is the operator[] access, where the
 * application <b>must</b> set the length to a high enough value
 * before using the operator[].
 *
 * Implementors that cater to high-performance applications tend to
 * exploit this latitude to the extreme, basically reasoning that
 * correct applications will behave normally, while incorrect
 * applications will crash, but those crashes will be detected during
 * development/testing.
 *
 * Realizing that this may be a bad tradeoff some implementors offer
 * compile-time hooks to control the behavior of sequences when used
 * improperly, some implementors may go as far as using run-time
 * hooks.
 *
 * The implementation of sequences calls the following template class
 * in points where the application may trigger undefined behavior.
 * The application developer can use partial (or full) template
 * specialization to introduce her own code at these critical points.
 *
 * Some examples may help, suppose you want to change your application
 * so for all sequence types the operator[] raises an exception if the
 * index is out of range.  Then you would provide the following
 * (partial) template specialization:
 *
 * <PRE>
 * template<typename T>
 * struct range_checking<T,true> {
 *   void check(CORBA::ULong index, CORBA::ULong length) {
 *     if (index < length)
 *       return;
 *     throw std::range_error("CORBA sequence range error");
 *   };
 * ...
 * ..
 * };
 * </PRE>
 *
 * This specialization must be introduced before any sequence code is
 * seen, therefore, the application would also need to define the
 * following macro in their $ACE_ROOT/ace/config.h file:
 *
 * - #define TAO_USER_DEFINED_SEQUENCE_SAFETY_TRAITS_INCLUDE "<filename here>"
 *
 * Likewise, if the application only wanted to check the range for a
 * special type, say some structure MyStruct, then they would provide
 * a full specialization.  Just for giggles, we will also introduce
 * run-time controls to this example:
 *
 * <PRE>
 * template<>
 * struct safety_traits<tao::details::value_traits<MyStruct>,true> {
 *   bool enable_range_checking;
 *   void check_range(CORBA::ULong index, CORBA::ULong length) {
 *     if (!enable_range_checking || index < length)
 *       return;
 *     throw std::range_error("CORBA sequence range error");
 *   };
 * ...
 * ..
 * };
 * </PRE>
 *
 *
 *
 * @todo There is no control on a per-sequence type basis, only on a
 *       per-underlying type basis, for example, the following two IDL
 *       sequences would get the same behavior:
 *       // IDL
 *       typedef sequence<MyStruct> MyStructSequence;
 *       typedef sequence<MyStruct> MyStructList;
 *
 * @todo There is no way to control behavior on a per-sequence basis,
 *       i.e. to have some sequences of longs checked while others are
 *       not.  This is easy to fix, simply:
 *       - make all members of safety_traits non-static
 *       - have each sequence contain their own instance of
 *         safety_traits
 *       - grant users read/write access to the safety_traits of each
 *         sequence
 *       but there are footprint consequences to that approach.  Until
 *       there is more demand to justify the cost, I will not
 *       implement such a change.
 */
template<typename T, bool dummy>
struct range_checking
{
  typedef T value_type;

  inline static void check(
      CORBA::ULong /* index */,
      CORBA::ULong /* length */,
      CORBA::ULong /* maximum */,
      char const * /* function_name */)
  {
    // Applications and tests can specialize this function to define
    // their own behavior
  }

  inline static void check_length(
      CORBA::ULong & /* new_length */,
      CORBA::ULong /* maximum */)
  {
    /*
    if (maximum < new_length)
      new_length = maximum;
    */
  }
};

} // namespace details
} // namespace TAO

TAO_END_VERSIONED_NAMESPACE_DECL

#if defined(TAO_USER_DEFINED_SEQUENCE_RANGE_CHECKING_INCLUDE)
#  include TAO_USER_DEFINED_SEQUENCE_RANGE_CHECKING_INCLUDE
#endif // TAO_USER_DEFINED_SEQUENCE_RANGE_CHECKING_INCLUDE

#endif // guard_range_checking_hpp