~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000 MySQL AB
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; version 2 of the License.
6
7
   This program is distributed in the hope that it will be useful,
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
   GNU General Public License for more details.
11
12
   You should have received a copy of the GNU General Public License
13
   along with this program; if not, write to the Free Software
1802.10.2 by Monty Taylor
Update all of the copyright headers to include the correct address.
14
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
1 by brian
clean slate
15
1441.2.3 by Tim Martin
Updating existing comments to doxygen format
16
/**
17
 * @file
18
 * Routines to handle mallocing of results which will be freed the same time 
19
 */
1 by brian
clean slate
20
2173.2.1 by Monty Taylor
Fixes incorrect usage of include
21
#include <config.h>
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
22
2241.4.14 by Stewart Smith
remove some includes from my_sys.h and instead only include where needed. This helps reduce the number of files that have to be rebuilt when you change some of the more widely included header files (such as the drizzled::identifier ones)
23
#include <drizzled/definitions.h>
24
#include <drizzled/memory/root.h>
2173.2.1 by Monty Taylor
Fixes incorrect usage of include
25
#include <drizzled/internal/my_sys.h>
26
#include <drizzled/internal/m_string.h>
2318.6.29 by Olaf van der Spek
Refactor
27
#include <drizzled/sql_string.h>
1 by brian
clean slate
28
1067.4.10 by Nathan Williams
Converted all cmin/cmax usages in the mysys directory to std::min/max.
29
#include <algorithm>
30
31
using namespace std;
1253.1.3 by Monty Taylor
MEM_ROOT == memory::Root
32
2318.6.21 by Olaf van der Spek
Refactor
33
namespace drizzled {
2318.6.29 by Olaf van der Spek
Refactor
34
namespace memory {
1 by brian
clean slate
35
1253.1.2 by Monty Taylor
We have init_sql_alloc and init_alloc_root - and I can't tell the difference.
36
static const unsigned int MAX_BLOCK_TO_DROP= 4096;
37
static const unsigned int MAX_BLOCK_USAGE_BEFORE_DROP= 10;
38
1441.2.1 by Tim Martin
Reformatting some memory/root.h comments for doxygen
39
/**
40
 * @brief
41
 * Initialize memory root
42
 *
43
 * @details
44
 * This function prepares memory root for further use, sets initial size of
45
 * chunk for memory allocation and pre-allocates first block if specified.
46
 * Altough error can happen during execution of this function if
47
 * pre_alloc_size is non-0 it won't be reported. Instead it will be
2318.6.41 by Olaf van der Spek
Refactor
48
 * reported as error in first alloc() on this memory root.
1441.2.1 by Tim Martin
Reformatting some memory/root.h comments for doxygen
49
 *
50
 * @param  mem_root       memory root to initialize
51
 * @param  block_size     size of chunks (blocks) used for memory allocation
52
 *                       (It is external size of chunk i.e. it should include
53
 *                      memory required for internal structures, thus it
2318.6.29 by Olaf van der Spek
Refactor
54
 *                      should be no less than ROOT_MIN_BLOCK_SIZE)
1441.2.1 by Tim Martin
Reformatting some memory/root.h comments for doxygen
55
 *
56
 */
2318.6.29 by Olaf van der Spek
Refactor
57
void Root::init(size_t block_size_arg)
1 by brian
clean slate
58
{
1487 by Brian Aker
More updates for memory::Root
59
  free= used= pre_alloc= 0;
60
  min_malloc= 32;
2318.6.29 by Olaf van der Spek
Refactor
61
  block_size= block_size_arg - ROOT_MIN_BLOCK_SIZE;
1487 by Brian Aker
More updates for memory::Root
62
  block_num= 4;			/* We shift this with >>2 */
63
  first_block_usage= 0;
1 by brian
clean slate
64
}
65
1441.2.1 by Tim Martin
Reformatting some memory/root.h comments for doxygen
66
/**
67
 * @details
68
 * Function aligns and assigns new value to block size; then it tries to
69
 * reuse one of existing blocks as prealloc block, or malloc new one of
70
 * requested size. If no blocks can be reused, all unused blocks are freed
71
 * before allocation.
72
 *
73
 * @param  mem_root        memory root to change defaults of
74
 * @param  block_size      new value of block size. Must be greater or equal
75
 *                         than ALLOC_ROOT_MIN_BLOCK_SIZE (this value is about
76
 *                         68 bytes and depends on platform and compilation flags)
77
 * @param pre_alloc_size  new size of preallocated block. If not zero,
78
 *                        must be equal to or greater than block size,
79
 *                        otherwise means 'no prealloc'.
80
 */
2318.6.29 by Olaf van der Spek
Refactor
81
void Root::reset_defaults(size_t block_size_arg, size_t pre_alloc_size)
1 by brian
clean slate
82
{
2318.6.29 by Olaf van der Spek
Refactor
83
  block_size= block_size_arg - ROOT_MIN_BLOCK_SIZE;
1 by brian
clean slate
84
  if (pre_alloc_size)
85
  {
2318.6.29 by Olaf van der Spek
Refactor
86
    size_t size= pre_alloc_size + ALIGN_SIZE(sizeof(internal::UsedMemory));
1485 by Brian Aker
Updates to confine memroot
87
    if (not pre_alloc || pre_alloc->size != size)
1 by brian
clean slate
88
    {
2318.6.29 by Olaf van der Spek
Refactor
89
      internal::UsedMemory *mem, **prev= &this->free;
1 by brian
clean slate
90
      /*
91
        Free unused blocks, so that consequent calls
92
        to reset_root_defaults won't eat away memory.
93
      */
94
      while (*prev)
95
      {
96
        mem= *prev;
97
        if (mem->size == size)
98
        {
99
          /* We found a suitable block, no need to do anything else */
1485 by Brian Aker
Updates to confine memroot
100
          pre_alloc= mem;
1 by brian
clean slate
101
          return;
102
        }
2318.6.29 by Olaf van der Spek
Refactor
103
        if (mem->left + ALIGN_SIZE(sizeof(internal::UsedMemory)) == mem->size)
1 by brian
clean slate
104
        {
105
          /* remove block from the list and free it */
106
          *prev= mem->next;
1485 by Brian Aker
Updates to confine memroot
107
          std::free(mem);
1 by brian
clean slate
108
        }
109
        else
110
          prev= &mem->next;
111
      }
112
      /* Allocate new prealloc block and add it to the end of free list */
2318.6.29 by Olaf van der Spek
Refactor
113
      mem= static_cast<internal::UsedMemory *>(malloc(size));
2318.4.11 by Olaf van der Spek
New doesn't return NULL.
114
      mem->size= size;
115
      mem->left= pre_alloc_size;
116
      mem->next= *prev;
117
      *prev= pre_alloc= mem;
1 by brian
clean slate
118
    }
119
  }
120
  else
779.1.27 by Monty Taylor
Got rid of __attribute__((unused)) and the like from the .cc files.
121
  {
1485 by Brian Aker
Updates to confine memroot
122
    pre_alloc= 0;
779.1.27 by Monty Taylor
Got rid of __attribute__((unused)) and the like from the .cc files.
123
  }
1 by brian
clean slate
124
}
125
1441.2.5 by Tim Martin
More doxygen commenting
126
/**
127
 * @brief 
128
 * Allocate a chunk of memory from the Root structure provided, 
129
 * obtaining more memory from the heap if necessary
130
 *
131
 * @pre
2318.6.23 by Olaf van der Spek
Refactor
132
 * mem_root must have been initialised via init()
1441.2.5 by Tim Martin
More doxygen commenting
133
 *
134
 * @param  mem_root  The memory Root to allocate from
135
 * @param  length    The size of the block to allocate
136
 *
137
 * @todo Would this be more suitable as a member function on the
138
 * Root class?
139
 */
2318.6.41 by Olaf van der Spek
Refactor
140
unsigned char* Root::alloc(size_t length)
1485 by Brian Aker
Updates to confine memroot
141
{
2318.6.29 by Olaf van der Spek
Refactor
142
  internal::UsedMemory *next= NULL;
1487 by Brian Aker
More updates for memory::Root
143
  assert(alloc_root_inited());
1 by brian
clean slate
144
145
  length= ALIGN_SIZE(length);
2318.6.30 by Olaf van der Spek
Refactor
146
  internal::UsedMemory **prev= &this->free;
147
  if (*prev)
1 by brian
clean slate
148
  {
149
    if ((*prev)->left < length &&
1486 by Brian Aker
More encapsulation.
150
	this->first_block_usage++ >= MAX_BLOCK_USAGE_BEFORE_DROP &&
1253.1.2 by Monty Taylor
We have init_sql_alloc and init_alloc_root - and I can't tell the difference.
151
	(*prev)->left < MAX_BLOCK_TO_DROP)
1 by brian
clean slate
152
    {
153
      next= *prev;
154
      *prev= next->next;			/* Remove block from list */
1486 by Brian Aker
More encapsulation.
155
      next->next= this->used;
156
      this->used= next;
157
      this->first_block_usage= 0;
1 by brian
clean slate
158
    }
2318.6.30 by Olaf van der Spek
Refactor
159
    for (next= *prev; next && next->left < length; next= next->next)
1 by brian
clean slate
160
      prev= &next->next;
161
  }
162
  if (! next)
163
  {						/* Time to alloc new block */
2318.6.30 by Olaf van der Spek
Refactor
164
    size_t tmp_block_size= this->block_size * (this->block_num >> 2);
165
    size_t get_size= length+ALIGN_SIZE(sizeof(internal::UsedMemory));
1486 by Brian Aker
More encapsulation.
166
    get_size= max(get_size, tmp_block_size);
1 by brian
clean slate
167
2318.6.29 by Olaf van der Spek
Refactor
168
    next = static_cast<internal::UsedMemory *>(malloc(get_size));
1486 by Brian Aker
More encapsulation.
169
    this->block_num++;
1 by brian
clean slate
170
    next->next= *prev;
171
    next->size= get_size;
2318.6.29 by Olaf van der Spek
Refactor
172
    next->left= get_size-ALIGN_SIZE(sizeof(internal::UsedMemory));
1 by brian
clean slate
173
    *prev=next;
174
  }
175
2318.6.21 by Olaf van der Spek
Refactor
176
  unsigned char* point= (unsigned char*) ((char*) next+ (next->size-next->left));
1486 by Brian Aker
More encapsulation.
177
  /** @todo next part may be unneeded due to this->first_block_usage counter*/
178
  if ((next->left-= length) < this->min_malloc)
1 by brian
clean slate
179
  {						/* Full block */
180
    *prev= next->next;				/* Remove block from list */
1486 by Brian Aker
More encapsulation.
181
    next->next= this->used;
182
    this->used= next;
183
    this->first_block_usage= 0;
1 by brian
clean slate
184
  }
1441.2.5 by Tim Martin
More doxygen commenting
185
186
  return point;
1 by brian
clean slate
187
}
188
189
1441.2.3 by Tim Martin
Updating existing comments to doxygen format
190
/**
191
 * @brief
192
 * Allocate many pointers at the same time.
193
 *
194
 * @details
195
 * The variable arguments are a list of alternating pointers and lengths,
196
 * terminated by a null pointer:
2318.6.29 by Olaf van der Spek
Refactor
197
 * @li <tt>char* * pointer1</tt>
1441.2.3 by Tim Martin
Updating existing comments to doxygen format
198
 * @li <tt>uint length1</tt>
2318.6.29 by Olaf van der Spek
Refactor
199
 * @li <tt>char* * pointer2</tt>
1441.2.3 by Tim Martin
Updating existing comments to doxygen format
200
 * @li <tt>uint length2</tt>
201
 * @li <tt>...</tt>
202
 * @li <tt>NULL</tt>
203
 *
204
 * @c pointer1, @c pointer2 etc. all point into big allocated memory area
205
 *
206
 * @param root  Memory root
207
 *
208
 * @return
209
 * A pointer to the beginning of the allocated memory block in case of 
210
 * success or NULL if out of memory
211
 */
2318.6.41 by Olaf van der Spek
Refactor
212
void* Root::multi_alloc(int unused, ...)
1 by brian
clean slate
213
{
214
  va_list args;
2318.6.29 by Olaf van der Spek
Refactor
215
  char* *ptr, *start, *res;
1 by brian
clean slate
216
  size_t tot_length, length;
217
1532.1.9 by Brian Aker
Fix for Solaris build issue.
218
  (void)unused; // For some reason Sun Studio registers unused as not used.
1532.1.7 by Brian Aker
Fix for non-portable vastart usage.
219
  va_start(args, unused);
1 by brian
clean slate
220
  tot_length= 0;
2318.6.29 by Olaf van der Spek
Refactor
221
  while ((ptr= va_arg(args, char* *)))
1 by brian
clean slate
222
  {
223
    length= va_arg(args, uint);
224
    tot_length+= ALIGN_SIZE(length);
225
  }
226
  va_end(args);
227
2318.6.41 by Olaf van der Spek
Refactor
228
  start= (char*) this->alloc(tot_length);
1 by brian
clean slate
229
1532.1.7 by Brian Aker
Fix for non-portable vastart usage.
230
  va_start(args, unused);
1 by brian
clean slate
231
  res= start;
2318.6.29 by Olaf van der Spek
Refactor
232
  while ((ptr= va_arg(args, char* *)))
1 by brian
clean slate
233
  {
234
    *ptr= res;
235
    length= va_arg(args, uint);
236
    res+= ALIGN_SIZE(length);
237
  }
238
  va_end(args);
51.3.20 by Jay Pipes
Phase 6 - Remove DBUG from mysys
239
  return((void*) start);
1 by brian
clean slate
240
}
241
1441.2.3 by Tim Martin
Updating existing comments to doxygen format
242
/**
243
 * @brief
244
 * Mark all data in blocks free for reusage 
1441.2.5 by Tim Martin
More doxygen commenting
245
 */
2318.6.29 by Olaf van der Spek
Refactor
246
void Root::mark_blocks_free()
1 by brian
clean slate
247
{
2318.6.29 by Olaf van der Spek
Refactor
248
  internal::UsedMemory *next;
249
  internal::UsedMemory **last;
1 by brian
clean slate
250
251
  /* iterate through (partially) free blocks, mark them free */
1485 by Brian Aker
Updates to confine memroot
252
  last= &free;
253
  for (next= free; next; next= *(last= &next->next))
1 by brian
clean slate
254
  {
2318.6.29 by Olaf van der Spek
Refactor
255
    next->left= next->size - ALIGN_SIZE(sizeof(internal::UsedMemory));
1 by brian
clean slate
256
  }
257
258
  /* Combine the free and the used list */
1485 by Brian Aker
Updates to confine memroot
259
  *last= next= used;
1 by brian
clean slate
260
261
  /* now go through the used blocks and mark them free */
262
  for (; next; next= next->next)
263
  {
2318.6.29 by Olaf van der Spek
Refactor
264
    next->left= next->size - ALIGN_SIZE(sizeof(internal::UsedMemory));
1 by brian
clean slate
265
  }
266
267
  /* Now everything is set; Indicate that nothing is used anymore */
1485 by Brian Aker
Updates to confine memroot
268
  used= 0;
269
  first_block_usage= 0;
1 by brian
clean slate
270
}
271
1441.2.3 by Tim Martin
Updating existing comments to doxygen format
272
/**
273
 * @brief
2318.6.29 by Olaf van der Spek
Refactor
274
 * Deallocate everything used by alloc_root or just move
1441.2.3 by Tim Martin
Updating existing comments to doxygen format
275
 * used blocks to free list if called with MY_USED_TO_FREE
276
 *
277
 * @note
278
 * One can call this function either with root block initialised with
2318.6.23 by Olaf van der Spek
Refactor
279
 * init() or with a zero:ed block.
1441.2.3 by Tim Martin
Updating existing comments to doxygen format
280
 * It's also safe to call this multiple times with the same mem_root.
281
 *
282
 * @param   root     Memory root
283
 * @param   MyFlags  Flags for what should be freed:
284
 *   @li   MARK_BLOCKS_FREED	Don't free blocks, just mark them free
285
 *   @li   KEEP_PREALLOC        If this is not set, then free also the
286
 *        		        preallocated block
287
 */
2318.6.29 by Olaf van der Spek
Refactor
288
void Root::free_root(myf MyFlags)
1 by brian
clean slate
289
{
2318.6.29 by Olaf van der Spek
Refactor
290
  if (MyFlags & MARK_BLOCKS_FREE)
1 by brian
clean slate
291
  {
1487 by Brian Aker
More updates for memory::Root
292
    this->mark_blocks_free();
51.3.20 by Jay Pipes
Phase 6 - Remove DBUG from mysys
293
    return;
1 by brian
clean slate
294
  }
2318.6.29 by Olaf van der Spek
Refactor
295
  if (!(MyFlags & KEEP_PREALLOC))
1487 by Brian Aker
More updates for memory::Root
296
    this->pre_alloc=0;
1 by brian
clean slate
297
2318.6.30 by Olaf van der Spek
Refactor
298
  for (internal::UsedMemory* next= this->used; next;)
1 by brian
clean slate
299
  {
2318.6.30 by Olaf van der Spek
Refactor
300
    internal::UsedMemory* old =next; 
301
    next= next->next;
1487 by Brian Aker
More updates for memory::Root
302
    if (old != this->pre_alloc)
303
      std::free(old);
1 by brian
clean slate
304
  }
2318.6.30 by Olaf van der Spek
Refactor
305
  for (internal::UsedMemory* next=this->free; next;)
1 by brian
clean slate
306
  {
2318.6.30 by Olaf van der Spek
Refactor
307
    internal::UsedMemory* old= next; 
308
    next= next->next;
1487 by Brian Aker
More updates for memory::Root
309
    if (old != this->pre_alloc)
310
      std::free(old);
1 by brian
clean slate
311
  }
1487 by Brian Aker
More updates for memory::Root
312
  this->used=this->free=0;
313
  if (this->pre_alloc)
1 by brian
clean slate
314
  {
1487 by Brian Aker
More updates for memory::Root
315
    this->free=this->pre_alloc;
2318.6.29 by Olaf van der Spek
Refactor
316
    this->free->left=this->pre_alloc->size-ALIGN_SIZE(sizeof(internal::UsedMemory));
1487 by Brian Aker
More updates for memory::Root
317
    this->free->next=0;
1 by brian
clean slate
318
  }
1487 by Brian Aker
More updates for memory::Root
319
  this->block_num= 4;
320
  this->first_block_usage= 0;
1 by brian
clean slate
321
}
322
1441.2.5 by Tim Martin
More doxygen commenting
323
/**
324
 * @brief
325
 * Duplicate a null-terminated string into memory allocated from within the
326
 * specified Root
327
 */
2318.6.29 by Olaf van der Spek
Refactor
328
char* Root::strdup(const char* str)
1 by brian
clean slate
329
{
2318.9.10 by Olaf van der Spek
Rename strmake to strdup (standard name)
330
  return strdup(str, strlen(str));
1 by brian
clean slate
331
}
332
1441.2.5 by Tim Martin
More doxygen commenting
333
/**
334
 * @brief
335
 * Copy the (not necessarily null-terminated) string into memory allocated
336
 * from within the specified Root
337
 *
338
 * @details
339
 * Note that the string is copied according to the length specified, so
340
 * null-termination is ignored. The duplicated string will be null-terminated,
341
 * even if the original string wasn't (one additional byte is allocated for
342
 * this purpose).
343
 */
2318.9.10 by Olaf van der Spek
Rename strmake to strdup (standard name)
344
char* Root::strdup(const char* str, size_t len)
1 by brian
clean slate
345
{
2318.6.40 by Olaf van der Spek
Refactor
346
  char* pos= (char*)alloc(len + 1);
2318.6.21 by Olaf van der Spek
Refactor
347
  memcpy(pos, str, len);
348
  pos[len]= 0;
1 by brian
clean slate
349
  return pos;
350
}
351
2318.9.10 by Olaf van der Spek
Rename strmake to strdup (standard name)
352
char* Root::strdup(str_ref v)
353
{
354
  return strdup(v.data(), v.size());
2318.6.29 by Olaf van der Spek
Refactor
355
}
356
1441.2.5 by Tim Martin
More doxygen commenting
357
/**
358
 * @brief
359
 * Duplicate the provided block into memory allocated from within the specified
360
 * Root
361
 *
362
 * @return
363
 * non-NULL pointer to a copy of the data if memory could be allocated, otherwise
364
 * NULL
365
 */
2318.6.29 by Olaf van der Spek
Refactor
366
void* Root::memdup(const void* str, size_t len)
1 by brian
clean slate
367
{
2318.6.40 by Olaf van der Spek
Refactor
368
  void* pos= alloc(len);
2318.6.21 by Olaf van der Spek
Refactor
369
  memcpy(pos, str, len);
1 by brian
clean slate
370
  return pos;
371
}
1253.1.3 by Monty Taylor
MEM_ROOT == memory::Root
372
2318.6.29 by Olaf van der Spek
Refactor
373
}
1253.1.3 by Monty Taylor
MEM_ROOT == memory::Root
374
} /* namespace drizzled */