~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/memory/root.cc

Merge Monty

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
 
23
23
using namespace std;
24
24
 
 
25
namespace drizzled
 
26
{
 
27
 
 
28
static const unsigned int MAX_BLOCK_TO_DROP= 4096;
 
29
static const unsigned int MAX_BLOCK_USAGE_BEFORE_DROP= 10;
 
30
 
25
31
/*
26
32
  Initialize memory root
27
33
 
28
34
  SYNOPSIS
29
 
    init_alloc_root()
 
35
    memory::init_alloc_root()
30
36
      mem_root       - memory root to initialize
31
37
      block_size     - size of chunks (blocks) used for memory allocation
32
38
                       (It is external size of chunk i.e. it should include
33
39
                        memory required for internal structures, thus it
34
 
                        should be no less than ALLOC_ROOT_MIN_BLOCK_SIZE)
35
 
      pre_alloc_size - if non-0, then size of block that should be
36
 
                       pre-allocated during memory root initialization.
 
40
                        should be no less than memory::ROOT_MIN_BLOCK_SIZE)
37
41
 
38
42
  DESCRIPTION
39
43
    This function prepares memory root for further use, sets initial size of
43
47
    reported as error in first alloc_root() on this memory root.
44
48
*/
45
49
 
46
 
void init_alloc_root(MEM_ROOT *mem_root, size_t block_size,
47
 
                     size_t )
 
50
void memory::init_alloc_root(memory::Root *mem_root, size_t block_size)
48
51
{
49
52
  mem_root->free= mem_root->used= mem_root->pre_alloc= 0;
50
53
  mem_root->min_malloc= 32;
51
 
  mem_root->block_size= block_size - ALLOC_ROOT_MIN_BLOCK_SIZE;
 
54
  mem_root->block_size= block_size - memory::ROOT_MIN_BLOCK_SIZE;
52
55
  mem_root->error_handler= 0;
53
56
  mem_root->block_num= 4;                       /* We shift this with >>2 */
54
57
  mem_root->first_block_usage= 0;
74
77
    before allocation.
75
78
*/
76
79
 
77
 
void reset_root_defaults(MEM_ROOT *mem_root, size_t block_size,
78
 
                         size_t pre_alloc_size)
 
80
void memory::reset_root_defaults(memory::Root *mem_root, size_t block_size,
 
81
                                 size_t pre_alloc_size)
79
82
{
80
83
  assert(alloc_root_inited(mem_root));
81
84
 
82
 
  mem_root->block_size= block_size - ALLOC_ROOT_MIN_BLOCK_SIZE;
 
85
  mem_root->block_size= block_size - memory::ROOT_MIN_BLOCK_SIZE;
83
86
  if (pre_alloc_size)
84
87
  {
85
 
    size_t size= pre_alloc_size + ALIGN_SIZE(sizeof(USED_MEM));
 
88
    size_t size= pre_alloc_size + ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
86
89
    if (!mem_root->pre_alloc || mem_root->pre_alloc->size != size)
87
90
    {
88
 
      USED_MEM *mem, **prev= &mem_root->free;
 
91
      memory::internal::UsedMemory *mem, **prev= &mem_root->free;
89
92
      /*
90
93
        Free unused blocks, so that consequent calls
91
94
        to reset_root_defaults won't eat away memory.
99
102
          mem_root->pre_alloc= mem;
100
103
          return;
101
104
        }
102
 
        if (mem->left + ALIGN_SIZE(sizeof(USED_MEM)) == mem->size)
 
105
        if (mem->left + ALIGN_SIZE(sizeof(memory::internal::UsedMemory)) == mem->size)
103
106
        {
104
107
          /* remove block from the list and free it */
105
108
          *prev= mem->next;
109
112
          prev= &mem->next;
110
113
      }
111
114
      /* Allocate new prealloc block and add it to the end of free list */
112
 
      if ((mem= (USED_MEM *) malloc(size)))
 
115
      if ((mem= static_cast<memory::internal::UsedMemory *>(malloc(size))))
113
116
      {
114
117
        mem->size= size;
115
118
        mem->left= pre_alloc_size;
129
132
}
130
133
 
131
134
 
132
 
void *alloc_root(MEM_ROOT *mem_root, size_t length)
 
135
void *memory::alloc_root(memory::Root *mem_root, size_t length)
133
136
{
134
137
  size_t get_size, block_size;
135
138
  unsigned char* point;
136
 
  register USED_MEM *next= 0;
137
 
  register USED_MEM **prev;
 
139
  memory::internal::UsedMemory *next= NULL;
 
140
  memory::internal::UsedMemory **prev;
138
141
  assert(alloc_root_inited(mem_root));
139
142
 
140
143
  length= ALIGN_SIZE(length);
141
144
  if ((*(prev= &mem_root->free)) != NULL)
142
145
  {
143
146
    if ((*prev)->left < length &&
144
 
        mem_root->first_block_usage++ >= ALLOC_MAX_BLOCK_USAGE_BEFORE_DROP &&
145
 
        (*prev)->left < ALLOC_MAX_BLOCK_TO_DROP)
 
147
        mem_root->first_block_usage++ >= MAX_BLOCK_USAGE_BEFORE_DROP &&
 
148
        (*prev)->left < MAX_BLOCK_TO_DROP)
146
149
    {
147
150
      next= *prev;
148
151
      *prev= next->next;                        /* Remove block from list */
156
159
  if (! next)
157
160
  {                                             /* Time to alloc new block */
158
161
    block_size= mem_root->block_size * (mem_root->block_num >> 2);
159
 
    get_size= length+ALIGN_SIZE(sizeof(USED_MEM));
 
162
    get_size= length+ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
160
163
    get_size= max(get_size, block_size);
161
164
 
162
 
    if (!(next = (USED_MEM*) malloc(get_size)))
 
165
    if (!(next = static_cast<memory::internal::UsedMemory *>(malloc(get_size))))
163
166
    {
164
167
      if (mem_root->error_handler)
165
168
        (*mem_root->error_handler)();
166
 
      return((void*) 0);
 
169
      return NULL;
167
170
    }
168
171
    mem_root->block_num++;
169
172
    next->next= *prev;
170
173
    next->size= get_size;
171
 
    next->left= get_size-ALIGN_SIZE(sizeof(USED_MEM));
 
174
    next->left= get_size-ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
172
175
    *prev=next;
173
176
  }
174
177
 
204
207
    in case of success or NULL if out of memory.
205
208
*/
206
209
 
207
 
void *multi_alloc_root(MEM_ROOT *root, ...)
 
210
void *memory::multi_alloc_root(memory::Root *root, ...)
208
211
{
209
212
  va_list args;
210
213
  char **ptr, *start, *res;
219
222
  }
220
223
  va_end(args);
221
224
 
222
 
  if (!(start= (char*) alloc_root(root, tot_length)))
 
225
  if (!(start= (char*) memory::alloc_root(root, tot_length)))
223
226
    return(0);
224
227
 
225
228
  va_start(args, root);
238
241
 
239
242
/* Mark all data in blocks free for reusage */
240
243
 
241
 
static inline void mark_blocks_free(MEM_ROOT* root)
 
244
static inline void mark_blocks_free(memory::Root* root)
242
245
{
243
 
  register USED_MEM *next;
244
 
  register USED_MEM **last;
 
246
  memory::internal::UsedMemory *next;
 
247
  memory::internal::UsedMemory **last;
245
248
 
246
249
  /* iterate through (partially) free blocks, mark them free */
247
250
  last= &root->free;
248
251
  for (next= root->free; next; next= *(last= &next->next))
249
252
  {
250
 
    next->left= next->size - ALIGN_SIZE(sizeof(USED_MEM));
 
253
    next->left= next->size - ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
251
254
    TRASH_MEM(next);
252
255
  }
253
256
 
257
260
  /* now go through the used blocks and mark them free */
258
261
  for (; next; next= next->next)
259
262
  {
260
 
    next->left= next->size - ALIGN_SIZE(sizeof(USED_MEM));
 
263
    next->left= next->size - ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
261
264
    TRASH_MEM(next);
262
265
  }
263
266
 
268
271
 
269
272
 
270
273
/*
271
 
  Deallocate everything used by alloc_root or just move
 
274
  Deallocate everything used by memory::alloc_root or just move
272
275
  used blocks to free list if called with MY_USED_TO_FREE
273
276
 
274
277
  SYNOPSIS
276
279
      root              Memory root
277
280
      MyFlags           Flags for what should be freed:
278
281
 
279
 
        MY_MARK_BLOCKS_FREED    Don't free blocks, just mark them free
280
 
        MY_KEEP_PREALLOC        If this is not set, then free also the
 
282
        MARK_BLOCKS_FREED       Don't free blocks, just mark them free
 
283
        KEEP_PREALLOC           If this is not set, then free also the
281
284
                                preallocated block
282
285
 
283
286
  NOTES
286
289
    It's also safe to call this multiple times with the same mem_root.
287
290
*/
288
291
 
289
 
void free_root(MEM_ROOT *root, myf MyFlags)
 
292
void memory::free_root(memory::Root *root, myf MyFlags)
290
293
{
291
 
  register USED_MEM *next,*old;
 
294
  memory::internal::UsedMemory *next,*old;
292
295
 
293
 
  if (MyFlags & MY_MARK_BLOCKS_FREE)
 
296
  if (MyFlags & memory::MARK_BLOCKS_FREE)
294
297
  {
295
298
    mark_blocks_free(root);
296
299
    return;
297
300
  }
298
 
  if (!(MyFlags & MY_KEEP_PREALLOC))
 
301
  if (!(MyFlags & memory::KEEP_PREALLOC))
299
302
    root->pre_alloc=0;
300
303
 
301
304
  for (next=root->used; next ;)
314
317
  if (root->pre_alloc)
315
318
  {
316
319
    root->free=root->pre_alloc;
317
 
    root->free->left=root->pre_alloc->size-ALIGN_SIZE(sizeof(USED_MEM));
 
320
    root->free->left=root->pre_alloc->size-ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
318
321
    TRASH_MEM(root->pre_alloc);
319
322
    root->free->next=0;
320
323
  }
327
330
  Find block that contains an object and set the pre_alloc to it
328
331
*/
329
332
 
330
 
void set_prealloc_root(MEM_ROOT *root, char *ptr)
 
333
void memory::set_prealloc_root(memory::Root *root, char *ptr)
331
334
{
332
 
  USED_MEM *next;
 
335
  memory::internal::UsedMemory *next;
333
336
  for (next=root->used; next ; next=next->next)
334
337
  {
335
338
    if ((char*) next <= ptr && (char*) next + next->size > ptr)
349
352
}
350
353
 
351
354
 
352
 
char *strdup_root(MEM_ROOT *root, const char *str)
 
355
char *memory::strdup_root(memory::Root *root, const char *str)
353
356
{
354
357
  return strmake_root(root, str, strlen(str));
355
358
}
356
359
 
357
360
 
358
 
char *strmake_root(MEM_ROOT *root, const char *str, size_t len)
 
361
char *memory::strmake_root(memory::Root *root, const char *str, size_t len)
359
362
{
360
363
  char *pos;
361
 
  if ((pos=(char *)alloc_root(root,len+1)))
 
364
  if ((pos=(char *)memory::alloc_root(root,len+1)))
362
365
  {
363
366
    memcpy(pos,str,len);
364
367
    pos[len]=0;
367
370
}
368
371
 
369
372
 
370
 
void *memdup_root(MEM_ROOT *root, const void *str, size_t len)
 
373
void *memory::memdup_root(memory::Root *root, const void *str, size_t len)
371
374
{
372
375
  void *pos;
373
 
  if ((pos=alloc_root(root,len)))
 
376
  if ((pos=memory::alloc_root(root,len)))
374
377
    memcpy(pos,str,len);
375
378
  return pos;
376
379
}
 
380
 
 
381
} /* namespace drizzled */