partition  0.1.1
 All Classes Namespaces Functions Variables Pages
partitionSafety.hpp
1 // partition: a container for organizing a set of sequential integers
2 // into non-overlapping groups.
3 // Version: 0.1.1
4 // Copyright 2013 Matthew T. Busche.
5 //
6 // This program is free software: you can redistribute it and/or modify it
7 // under the terms of the GNU General Public License as published by the Free
8 // Software Foundation, either version 3 of the License, or (at your option)
9 // any later version.
10 //
11 // This program is distributed in the hope that it will be useful, but WITHOUT
12 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 // more details.
15 //
16 // You should have received a copy of the GNU General Public License along
17 // with this program. If not, see <http://www.gnu.org/licenses/>.
18 
19 #ifndef PARTITIONSAFETY_HPP
20 #define PARTITIONSAFETY_HPP
21 
22 // Methods of Domain, Group, Group::Iterator and Group::ConstIterator validate
23 // caller input and verify that the state of the invoked object is compatible
24 // with the requested action, throwing exceptions when checks fail. Examples
25 // include:
26 //
27 // o Verifying that the id used to request a member mapping is within the
28 // Domain's range.
29 //
30 // o Verifying that a Group has been bound to a Domain before allowing a
31 // caller to add members to that Group.
32 //
33 // o Verifying that a Group Iterator is not pointing to the position
34 // before the front or after the back of the Group list before
35 // allowing the iterator to be dereferenced.
36 //
37 // Most checks have small overhead compared to the cost of the methods they
38 // safeguard; however, safety checks for some methods (like an iterator
39 // dereference) may be responsible for a significant fraction of the total
40 // processing of the method. The preprocessor macro PARTITION_SL (partition
41 // safety level) can be modified to eliminate some (or all) validations to
42 // achieve performance gains which may be useful to some programs.
43 // PARTITION_SL settings from 0 to 4 provide different levels of partition
44 // safety as summarized here:
45 //
46 // 0 : No validations are performed for any method.
47 //
48 // 1 : Validates constructor input and validates inputs that manipulate either
49 // the size of the Domain or the amount of memory reserved for the Domain.
50 // (It is expected that constructor and resize/reserve operations will
51 // be rare for the typical program and validating the inputs for these
52 // operations will not measurably impact performance.)
53 //
54 // 2 : Includes all other validations except validations in Iterator methods.
55 // (Iterator methods are quite short and are perhaps most impacted
56 // by their associated validation checks, so these validations are
57 // relegated to level 3.)
58 //
59 // 3 : Includes all validations.
60 //
61 // 4 : This level provides no additional validation but includes code that
62 // zeroes out certain data fields as an aid to debugging. (For example
63 // PARTITION_SL 4 ensures that the _prev and _next pointers of the
64 // Node structure are zeroed out when the Node is not in a Group list.
65 //
66 // Most programs that use partition will not measurably benefit from the
67 // removal of safety validations. Of those that do, a simple change to the
68 // PARTITION_SL setting will usually be adequate to eliminate undesirable
69 // safety overhead; but finer controls are provided that allow safety checks
70 // for specific groups of partition methods to be enabled or disabled.
71 //
72 // Class methods are organized into similar functional groups. Each group is
73 // assigned an independent preprocessor safety threshold setting. For
74 // example, all Iterator methods that dereference the iterator are assigned
75 // the preprocessor safety threshold setting PARTITION_ST_ITERATOR_DEREF. The
76 // validation checks for all methods in this functional group are included by
77 // the preprocessor if the value of PARTITION_SL is at least the value of
78 // PARTITION_ST_ITERATOR_DEREF. For clarity, here is an example of one method
79 // implementation:
80 //
81 // template<typename M, typename V>
82 // inline const typename Domain<M,V>::Entry& Group<M,V>::ConstIterator::operator*() const
83 // {
84 // #if PARTITION_SL >= PARTITION_ST_ITERATOR_DEREF
85 // _verifyNotAtEnd("operator*()");
86 // #endif
87 // return _node->_entry;
88 // }
89 //
90 // Lowering PARTITION_SL to any setting below the default value of
91 // PARTITION_ST_ITERATOR_DEREF will disable these safety checks, but that may
92 // also disable other safety checks you'd rather leave enabled. To disable
93 // safety checks only on methods that dereference iterators, instead raise the
94 // setting of PARTITION_ST_ITERATOR_DEREF to some number greater than
95 // PARTITION_SL. The default value of the partition safety level
96 // (PARTITION_SL) and the list of functional groups along with their
97 // respective default safety threshold settings (PARTITION_ST_*) are defined
98 // below.
99 
100 
101 // Default PARTITION_SL
102 //
103 #ifndef PARTITION_SL
104 #define PARTITION_SL 3
105 #endif
106 
107 // Default DEBUG threshold
108 //
109 #ifndef PARTITION_ST_DEBUG
110 #define PARTITION_ST_DEBUG 4
111 #endif
112 
113 // Default threshold for Domain constructors.
114 //
115 #ifndef PARTITION_ST_DOMAIN_CONSTRUCTOR
116 #define PARTITION_ST_DOMAIN_CONSTRUCTOR 1
117 #endif
118 
119 // Default threshold for operations that either resize the Domain or modify
120 // the amount of memory reserved for the Domain.
121 //
122 #ifndef PARTITION_ST_DOMAIN_MEMORY
123 #define PARTITION_ST_DOMAIN_MEMORY 1
124 #endif
125 
126 // Default threshold for operations that access (for reading or writing)
127 // existing members of the Domain.
128 //
129 #ifndef PARTITION_ST_DOMAIN_ACCESSOR
130 #define PARTITION_ST_DOMAIN_ACCESSOR 2
131 #endif
132 
133 // Default threshold for Group constructors.
134 //
135 #ifndef PARTITION_ST_GROUP_CONSTRUCTOR
136 #define PARTITION_ST_GROUP_CONSTRUCTOR 1
137 #endif
138 
139 // Default threshold for operations that read existing members of the Group.
140 // (This does include the non-const version of find.)
141 //
142 #ifndef PARTITION_ST_GROUP_ACCESSOR
143 #define PARTITION_ST_GROUP_ACCESSOR 2
144 #endif
145 
146 // Default threshold for operations that add new members to a Group.
147 //
148 #ifndef PARTITION_ST_GROUP_ADD
149 #define PARTITION_ST_GROUP_ADD 2
150 #endif
151 
152 // Default threshold for operations that remove members from a Group.
153 //
154 #ifndef PARTITION_ST_GROUP_REMOVE
155 #define PARTITION_ST_GROUP_REMOVE 2
156 #endif
157 
158 // Default threshold for the Iterator's ++ and -- operators.
159 //
160 #ifndef PARTITION_ST_ITERATOR_INC
161 #define PARTITION_ST_ITERATOR_INC 3
162 #endif
163 
164 // Default threshold for operations that dereference the iterator. (Note that
165 // validations for the Iterator::beforeFront() and Iterator::afterBack() are
166 // goverend by this threshold. Although these methods do not access the
167 // internal Node structure pointed to by the Iterator, they do dereference the
168 // Iterator's Group pointer.)
169 //
170 #ifndef PARTITION_ST_ITERATOR_DEREF
171 #define PARTITION_ST_ITERATOR_DEREF 3
172 #endif
173 
174 // Default threshold for operations that compare two iterators.
175 // (Comparing iterators from different groups is considered
176 // erroneous.)
177 //
178 #ifndef PARTITION_ST_ITERATOR_COMPARE
179 #define PARTITION_ST_ITERATOR_COMPARE 3
180 #endif
181 
182 // *****************************
183 // *** FOR INTERNAL USE ONLY ***
184 // *****************************
185 //
186 // The remaining preprocessor definitions are used internally to conditionally
187 // include verification tests.
188 //
189 #if PARTITION_SL >= PARTITION_ST_DOMAIN_CONSTRUCTOR
190 #define PARTITION_SAFETY_DOMAIN_CONSTRUCTOR(x) x
191 #else
192 #define PARTITION_SAFETY_DOMAIN_CONSTRUCTOR(x)
193 #endif
194 
195 #if PARTITION_SL >= PARTITION_ST_DOMAIN_MEMORY
196 #define PARTITION_SAFETY_DOMAIN_MEMORY(x) x
197 #else
198 #define PARTITION_SAFETY_DOMAIN_MEMORY(x)
199 #endif
200 
201 #if PARTITION_SL >= PARTITION_ST_DOMAIN_ACCESSOR
202 #define PARTITION_SAFETY_DOMAIN_ACCESSOR(x) x
203 #else
204 #define PARTITION_SAFETY_DOMAIN_ACCESSOR(x)
205 #endif
206 
207 #if PARTITION_SL >= PARTITION_ST_GROUP_CONSTRUCTOR
208 #define PARTITION_SAFETY_GROUP_CONSTRUCTOR(x) x
209 #else
210 #define PARTITION_SAFETY_GROUP_CONSTRUCTOR(x)
211 #endif
212 
213 #if PARTITION_SL >= PARTITION_ST_GROUP_ACCESSOR
214 #define PARTITION_SAFETY_GROUP_ACCESSOR(x) x
215 #else
216 #define PARTITION_SAFETY_GROUP_ACCESSOR(x)
217 #endif
218 
219 #if PARTITION_SL >= PARTITION_ST_GROUP_ADD
220 #define PARTITION_SAFETY_GROUP_ADD(x) x
221 #else
222 #define PARTITION_SAFETY_GROUP_ADD(x)
223 #endif
224 
225 #if PARTITION_SL >= PARTITION_ST_GROUP_REMOVE
226 #define PARTITION_SAFETY_GROUP_REMOVE(x) x
227 #else
228 #define PARTITION_SAFETY_GROUP_REMOVE(x)
229 #endif
230 
231 #if PARTITION_SL >= PARTITION_ST_INTERATOR_INC
232 #define PARTITION_SAFETY_INTERATOR_INC(x) x
233 #else
234 #define PARTITION_SAFETY_INTERATOR_INC(x)
235 #endif
236 
237 #if PARTITION_SL >= PARTITION_ST_ITERATOR_DEREF
238 #define PARTITION_SAFETY_ITERATOR_DEREF(x) x
239 #else
240 #define PARTITION_SAFETY_ITERATOR_DEREF(x)
241 #endif
242 
243 #if PARTITION_SL >= PARTITION_ST_ITERATOR_COMPARE
244 #define PARTITION_SAFETY_ITERATOR_COMPARE(x) x
245 #else
246 #define PARTITION_SAFETY_ITERATOR_COMPARE(x)
247 #endif
248 
249 #endif