]> www.ginac.de Git - cln.git/blob - src/base/cl_alloca.h
* src/numtheory/cl_nt_sqrtmodp.cc: #undef _R.
[cln.git] / src / base / cl_alloca.h
1 // cl_alloca().
2
3 #ifndef _CL_ALLOCA_H
4 #define _CL_ALLOCA_H
5
6 #include "cl_macros.h"
7 #include <stdlib.h>
8
9 namespace 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
43 struct cl_alloca_header {
44         cl_alloca_header* next;
45         long usable_memory[1]; // "long" guarantees alignment
46 };
47
48 extern cl_alloca_header* cl_alloc_alloca_header (size_t size);
49 extern void cl_free_alloca_header (cl_alloca_header* pointer);
50
51 class cl_alloca_stack {
52         cl_alloca_header* pointer;
53 public:
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 */