Table Of Contents
Previous Section Next Section

Program 94: Speed Kills

The new and delete function calls are costly. If you want to speed up your program and you know what you are doing, you can override them and create your own class-specific new and delete. That's what this programmer has done. The allocation algorithm is surprising simple, yet somehow memory gets corrupted. Why?

  1 /***********************************************
  2  * bit_test -- Test out our new high speed     *
  3  *      bit_array.                             *
  4  ***********************************************/
  5 #include <iostream>
  6 #include <memory.h>
  7
  8 // The size of a fast bit_array.
  9 // (Private to fast bit array)
 10 const int BIT_ARRAY_MAX = 64;   // Size in bits
 11
 12 // Number of bits in a byte
 13 const int BITS_PER_BYTE = 8;
 14 /************************************************
 15  * fast_bit_array -- A bit array using fast    *
 16  * allocate technology.                         *
 17  *                                              *
 18  * Member functions:                            *
 19  *      get -- Get an element from the          *
 20  *              array.                          *
 21  *      set -- Set the value of an element      *
 22  *              in the array.                   *
 23  *                                              *
 24  *      new -- used to quickly allocate a bit   *
 25  *              array.                          *
 26  *      delete -- used to quickly deallocate    *
 27  *                      a bit array.            *
 28  ************************************************/
 29 class fast_bit_array
 30 {
 31     protected:
 32         // Array data
 33         unsigned char
 34             data[BIT_ARRAY_MAX/BITS_PER_BYTE];
 35
 36     public:
 37         fast_bit_array(void)
 38         {
 39            memset(data, '\0', sizeof(data));
 40         }
 41         // Destructor defaults
 42     private:
 43         // No copy constructor
 44         fast_bit_array(const fast_bit_array &);
 45
 46         // No assignment operator
 47         fast_bit_array & operator =
 48             (const fast_bit_array &);
 49     public:
 50         // Set the value on an item
 51         void set(
 52             // Index into the array
 53             const unsigned int index,
 54
 55             // Value to put in the array
 56             const unsigned int value
 57         )
 58         {
 59             // Index into the bit in the byte
 60             unsigned int bit_index = index % 8;
 61
 62             // Byte in the array to use
 63             unsigned int byte_index = index / 8;
 64
 65             if (value)
 66             {
 67                 data[byte_index] |=
 68                     (1 << bit_index);
 69             }
 70             else
 71             {
 72                 data[byte_index] &=
 73                     ~(1 << bit_index);
 74             }
 75         }
 76         // Return the value of an element
 77         int get(unsigned int index)
 78         {
 79             // Index into the bit in the byte
 80             unsigned int bit_index = index % 8;
 81             // Byte in the array to use
 82             unsigned int byte_index = index / 8;
 83
 84             return (
 85                 (data[byte_index] &
 86                        (1 << bit_index)) != o);
 87        }
 88        // Allocate a new fast_bit_array
 89        void *operator new(const size_t);
 90
 91        // Delete a fast bit array.
 92        void operator delete(void *ptr);
 93 };
 94
 95 /************************************************
 96  * The following routines handle the local      *
 97  * new/delete for the fast_bit_array.           *
 98  ************************************************/
 99 // Max number of fast_bit_arrays we can use at once
100 const int N_FAST_BIT_ARRAYS = 30;
101
102 // If true, the bit array slot is allocated
103 // false indicates a free slot
104 static bool
105     bit_array_used[N_FAST_BIT_ARRAYS] = {false};
106
107 // Space for our fast bit arrays.
108 static char
109     bit_array_mem[N_FAST_BIT_ARRAYS]
110                 [sizeof(fast_bit_array)];
111
112 // Handle new for "fast_bit_array".
113 // (This is much quicker than the
114 //      system version of new)
115 /************************************************
116  * fast_bit_array -- new                        *
117  *                                              *
118  * This is a high speed allocation routine for  *
119  * the fast_bit_array class.   The method used  *
120  * for this is simple, but we know that only    *
121  * a few bit_arrays will be allocated.          *
122  *                                              *
123  * Returns a pointer to the new memory.         *
124  ************************************************/
125 void *fast_bit_array::operator new(const size_t)
126 {
127     int i;      // Index into the bit array slots
128
129     // Look for a free slot
130     for (i = 0; i < N_FAST_BIT_ARRAYS; ++i)
131     {
132         if (!bit_array_used[i])
133         {
134             // Free slot found, allocate the space
135             bit_array_used[i] = true;
136             return(bit_array_mem[i]);
137         }
138     }
139     std::cout << "Error: Out of local memory\n";
140     exit (8);
141 }
142
143 /************************************************
144  * fast_bit_array -- delete                     *
145  *                                              *
146  * Quickly free the space used by a             *
147  * fast bit array.                              *
148  ************************************************/
149 void fast_bit_array::operator delete(
150     void *ptr   // Pointer to the space to return
151 )
152 {
153     int i;      // Slot index
154
155     for (i = 0; i < N_FAST_BIT_ARRAYS; ++i)
156     {
157         // Is this the right slot
158         if (ptr == bit_array_mem[i])
159         {
160             // Right slot, free it
161             bit_array_used[i] = false;
162             return;
163         }
164     }
165     std::cout <<
166         "Error: Freed memory we didn't have\n";
167     exit (8);
168 }
169
170
171 /************************************************
172  * safe_bit_array -- A safer bit array.         *
173  *                                              *
174  * Like bit array, but with error checking.     *
175  ************************************************/
176 class safe_bit_array : public fast_bit_array
177 {
178     public:
179         // Sequence number generator
180         static int bit_array_counter;
181
182         // Our bit array number
183         int sequence;
184
185         safe_bit_array(void)
186         {
187             sequence = bit_array_counter;
188             ++bit_array_counter;
189         };
190         // Destructor defaults
191     private:
192         // No copy constructor
193         safe_bit_array(const safe_bit_array &);
194
195         // No assignment operator
196         safe_bit_array & operator = (
197                 const safe_bit_array &);
198     public:
199         // Set the value on an item
200         void set(
201             // Where to put the item
202             const unsigned int index,
203             // Item to put
204             const unsigned int value
205         )
206         {
207             if (index >= (BIT_ARRAY_MAX-1))
208             {
209                 std::cout <<
210                    "Bit array set error "
211                    "for bit array #"
212                    << sequence << "\n";
213                 exit (8);
214             }
215             fast_bit_array::set(index, value);
216         }
217         // Return the value of an element
218         int get(unsigned int index)
219         {
220             if (index >= (BIT_ARRAY_MAX-1))
221             {
222                 std::cout <<
223                    "Bit array get error "
224                    "for bit array #"
225                    << sequence << "\n";
226                 exit (8);
227             }
228             return (fast_bit_array::get(index));
229         }
230 };
231
232 // Sequence information
233 int safe_bit_array::bit_array_counter = 0;
234
235 int main()
236 {
237     // Create a nice new safe bit array
238     safe_bit_array *a_bit_array =
239         new safe_bit_array;
240
241     a_bit_array->set(5, 1);
242     // Return the bit_array to the system
243     delete a_bit_array;
244     return (0); 245 }

(Next Hint 305. Answer 56.)

Table Of Contents
Previous Section Next Section