PageRenderTime 31ms CodeModel.GetById 23ms app.highlight 6ms RepoModel.GetById 1ms app.codeStats 0ms

/cln-1.3.2/src/base/cl_alloca.h

#
C Header | 88 lines | 40 code | 14 blank | 34 comment | 5 complexity | 4cd9b3c0c6bcc3b7fc2c978a25fe2c49 MD5 | raw file
Possible License(s): GPL-2.0
 1// cl_alloca().
 2
 3#ifndef _CL_ALLOCA_H
 4#define _CL_ALLOCA_H
 5
 6#include "base/cl_macros.h"
 7#include <cstdlib>
 8
 9namespace cln {
10
11// Allocating temporary data of arbitrary size.
12// We prefer to allocate it on the stack instead of via malloc(), because
13// that's fully inlinable and causes less cache misses. But the global stack
14// size of applications is limited (typically 8 MB on Unix, 1 MB on Windows),
15// and we don't want users of CLN to need to change these limits. Therefore
16// we use stack allocation only for amounts < 64KB, and malloc() for larger
17// blocks.
18// Usage:
19//   {CL_ALLOCA_STACK;
20//    ...
21//    ... = cl_alloca(...);
22//    ...
23//    ... = cl_small_alloca(...);
24//    ...
25//    ... = cl_alloca(...);
26//    ...
27//   }
28// CL_ALLOCA_STACK declares that use of cl_alloca() and cl_small_alloca() is
29// possible. Then cl_alloca() and cl_small_alloca() can be used an arbitrary
30// number of times to get room.
31// The allocated room's extent ends at the end of the { ... } block.
32// In every C function CL_ALLOCA_STACK should only called once.
33// Because of a gcc bug, functions using these macros shouldn't be declared
34// inline.
35// cl_alloca(size) fetches a block of size bytes.
36// cl_small_alloca(size) fetches a block of size bytes, with size < 65536.
37// CL_SMALL_ALLOCA_STACK is similar to CL_ALLOCA_STACK, but allows only
38// the use of cl_small_alloca(), not cl_alloca().
39
40// CL_ALLOCA_STACK creates a variable containing a linked list of pointers
41// to be freed when the block is exited.
42
43struct cl_alloca_header {
44	cl_alloca_header* next;
45	long usable_memory[1]; // "long" guarantees alignment
46};
47
48extern cl_alloca_header* cl_alloc_alloca_header (size_t size);
49extern void cl_free_alloca_header (cl_alloca_header* pointer);
50
51class cl_alloca_stack {
52	cl_alloca_header* pointer;
53public:
54	cl_alloca_stack () { pointer = NULL; }
55	~cl_alloca_stack () { if (pointer) cl_free_alloca_header(pointer); }
56	void* push (cl_alloca_header* p) { p->next = pointer; pointer = p; return &p->usable_memory; }
57};
58
59#define CL_ALLOCA_STACK  \
60  cl_alloca_stack _alloca_stack
61
62#define CL_ALLOCA_MAX  65536
63
64#if defined(__GNUC__) && !defined(__riscos) && !defined(__convex__)
65  #define cl_alloca(size)  ((size) >= CL_ALLOCA_MAX ? _alloca_stack.push(cl_alloc_alloca_header(size)) : __builtin_alloca(size))
66  #define cl_small_alloca(size)  __builtin_alloca(size)
67  #define CL_SMALL_ALLOCA_STACK
68#elif !defined(NO_ALLOCA) && !defined(__sparc__) && !defined(__sparc64__)
69  #define cl_alloca(size)  ((size) >= CL_ALLOCA_MAX ? _alloca_stack.push(cl_alloc_alloca_header(size)) : alloca(size))
70  #define cl_small_alloca(size)  alloca(size)
71  #define CL_SMALL_ALLOCA_STACK
72#else
73  #define cl_alloca(size)  _alloca_stack.push(cl_alloc_alloca_header(size))
74  #define cl_small_alloca(size)  _alloca_stack.push(cl_alloc_alloca_header(size))
75  #define CL_SMALL_ALLOCA_STACK  CL_ALLOCA_STACK
76#endif
77
78// cl_alloc_array(type,size)
79// cl_small_alloc_array(type,size)
80// allocate an array with dynamic extent.
81  #define cl_alloc_array(arrayeltype,arraysize)  \
82    (arrayeltype*)cl_alloca((arraysize)*sizeof(arrayeltype))
83  #define cl_small_alloc_array(arrayeltype,arraysize)  \
84    (arrayeltype*)cl_small_alloca((arraysize)*sizeof(arrayeltype))
85
86}  // namespace cln
87
88#endif /* _CL_ALLOCA_H */