llvm-mos-sdk
atexit-impl.h
Go to the documentation of this file.
1 #ifndef ATEXIT_IMPL_H
2 #define ATEXIT_IMPL_H
3 
4 #include <cstdint>
5 
6 namespace __impl {
7 
8 struct ExitFunctionStorage {
9  void (*m_functionptr)(void *);
10  void *m_userdata;
11 
12  void operator()() const { m_functionptr(m_userdata); }
13 };
14 
15 /* Exit functions are registered in a singly-linked list of blocks of
16  * registrations. Each block contains 32 exit registrations, and additional
17  * space for registrations is allocated on the heap, as needed.*/
18 class RegistrationList {
19  // FnBlock is an array of function pointers and their arguments.
20  // The logical "front" of the block is the last item appended to
21  // the array.
22  struct FnBlock {
23  static constexpr std::uint8_t BLOCK_SZ = 32;
24 
25  ExitFunctionStorage m_funcs[BLOCK_SZ];
26  std::uint8_t m_sz;
27 
28  bool empty() const { return !m_sz; }
29  bool full() const { return m_sz == BLOCK_SZ; }
30 
31  void push_front(const ExitFunctionStorage &newfn) {
32  m_funcs[m_sz++] = newfn;
33  }
34 
35  const ExitFunctionStorage &back() const { return m_funcs[m_sz - 1]; }
36  void pop_back() { m_sz--; }
37  };
38 
39  struct FnNode : public FnBlock {
40  FnNode(FnBlock *next) : m_next{next} {}
41 
42  FnBlock *const m_next = nullptr;
43  };
44 
45  // The initial base node allows 32 exit registrations (1 block)
46  // of exit functions, without allocating. So the minumum required
47  // 32 exit functions will always be available.
48  FnBlock m_tail;
49  FnBlock *m_list = &m_tail;
50 
51 public:
52  bool push_front(const ExitFunctionStorage &new_exit);
53  void run_all_exits();
54 };
55 
56 } // namespace __impl
57 
58 #endif // not ATEXIT_IMPL_H
std::uint8_t
::uint8_t uint8_t
Definition: cstdint:21
cstdint