1 |
|
|
#ifndef SRC_CLEANUP_QUEUE_H_ |
2 |
|
|
#define SRC_CLEANUP_QUEUE_H_ |
3 |
|
|
|
4 |
|
|
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS |
5 |
|
|
|
6 |
|
|
#include <cstddef> |
7 |
|
|
#include <cstdint> |
8 |
|
|
#include <unordered_set> |
9 |
|
|
|
10 |
|
|
#include "memory_tracker.h" |
11 |
|
|
|
12 |
|
|
namespace node { |
13 |
|
|
|
14 |
|
|
class BaseObject; |
15 |
|
|
|
16 |
|
|
class CleanupQueue : public MemoryRetainer { |
17 |
|
|
public: |
18 |
|
|
typedef void (*Callback)(void*); |
19 |
|
|
|
20 |
|
13070 |
CleanupQueue() {} |
21 |
|
|
|
22 |
|
|
// Not copyable. |
23 |
|
|
CleanupQueue(const CleanupQueue&) = delete; |
24 |
|
|
|
25 |
|
74 |
SET_MEMORY_INFO_NAME(CleanupQueue) |
26 |
|
|
inline void MemoryInfo(node::MemoryTracker* tracker) const override; |
27 |
|
|
inline size_t SelfSize() const override; |
28 |
|
|
|
29 |
|
|
inline bool empty() const; |
30 |
|
|
|
31 |
|
|
inline void Add(Callback cb, void* arg); |
32 |
|
|
inline void Remove(Callback cb, void* arg); |
33 |
|
|
void Drain(); |
34 |
|
|
|
35 |
|
|
template <typename T> |
36 |
|
|
inline void ForEachBaseObject(T&& iterator) const; |
37 |
|
|
|
38 |
|
|
private: |
39 |
|
|
class CleanupHookCallback { |
40 |
|
|
public: |
41 |
|
2982960 |
CleanupHookCallback(Callback fn, |
42 |
|
|
void* arg, |
43 |
|
|
uint64_t insertion_order_counter) |
44 |
|
2982960 |
: fn_(fn), |
45 |
|
|
arg_(arg), |
46 |
|
2982960 |
insertion_order_counter_(insertion_order_counter) {} |
47 |
|
|
|
48 |
|
|
// Only hashes `arg_`, since that is usually enough to identify the hook. |
49 |
|
|
struct Hash { |
50 |
|
|
size_t operator()(const CleanupHookCallback& cb) const; |
51 |
|
|
}; |
52 |
|
|
|
53 |
|
|
// Compares by `fn_` and `arg_` being equal. |
54 |
|
|
struct Equal { |
55 |
|
|
bool operator()(const CleanupHookCallback& a, |
56 |
|
|
const CleanupHookCallback& b) const; |
57 |
|
|
}; |
58 |
|
|
|
59 |
|
|
private: |
60 |
|
|
friend class CleanupQueue; |
61 |
|
|
Callback fn_; |
62 |
|
|
void* arg_; |
63 |
|
|
|
64 |
|
|
// We keep track of the insertion order for these objects, so that we can |
65 |
|
|
// call the callbacks in reverse order when we are cleaning up. |
66 |
|
|
uint64_t insertion_order_counter_; |
67 |
|
|
}; |
68 |
|
|
|
69 |
|
|
inline BaseObject* GetBaseObject(const CleanupHookCallback& callback) const; |
70 |
|
|
|
71 |
|
|
// Use an unordered_set, so that we have efficient insertion and removal. |
72 |
|
|
std::unordered_set<CleanupHookCallback, |
73 |
|
|
CleanupHookCallback::Hash, |
74 |
|
|
CleanupHookCallback::Equal> |
75 |
|
|
cleanup_hooks_; |
76 |
|
|
uint64_t cleanup_hook_counter_ = 0; |
77 |
|
|
}; |
78 |
|
|
|
79 |
|
|
} // namespace node |
80 |
|
|
|
81 |
|
|
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS |
82 |
|
|
|
83 |
|
|
#endif // SRC_CLEANUP_QUEUE_H_ |