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