Line | Branch | Exec | Source |
---|---|---|---|
1 | #ifndef LYTHON_OBJECT_HEADER | ||
2 | #define LYTHON_OBJECT_HEADER | ||
3 | |||
4 | #include <memory> | ||
5 | |||
6 | #include "dependencies/coz_wrap.h" | ||
7 | #include "dtypes.h" | ||
8 | |||
9 | namespace lython { | ||
10 | |||
11 | struct GCObject { | ||
12 | public: | ||
13 | template <typename T, typename... Args> | ||
14 | T* new_object(Args&&... args) { | ||
15 | COZ_BEGIN("T::GCObject::new_object"); | ||
16 | |||
17 | 19810 | T* obj = GCObject::new_root<T>(args...); | |
18 | |||
19 | 19810 | add_child(obj); | |
20 | |||
21 | COZ_PROGRESS_NAMED("GCObject::new_object"); | ||
22 | COZ_END("T::GCObject::new_object"); | ||
23 | 19810 | return obj; | |
24 | } | ||
25 | |||
26 | template <typename T, typename... Args> | ||
27 | static T* new_root(Args&&... args) { | ||
28 | |||
29 | 19810 | auto& alloc = get_allocator<T>(); | |
30 | |||
31 | // allocate | ||
32 | 19810 | T* memory = alloc.allocate(1); | |
33 | |||
34 | // construct | ||
35 |
2/5✓ Branch 2 taken 9808 times.
✓ Branch 3 taken 95 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
19810 | T* obj = new ((void*)memory) T(std::forward<Args>(args)...); |
36 | 19810 | obj->class_id = meta::type_id<T>(); | |
37 | |||
38 | 19810 | return obj; | |
39 | } | ||
40 | |||
41 | template <typename T> | ||
42 | typename std::remove_const<T>::type* copy(T* obj) { | ||
43 | COZ_BEGIN("T::GCObject::copy"); | ||
44 | using NoConstT = typename std::remove_const<T>::type; | ||
45 | |||
46 | 188 | auto& alloc = get_allocator<NoConstT>(); | |
47 | |||
48 | // allocate | ||
49 | 188 | NoConstT* memory = alloc.allocate(1); | |
50 | // construct | ||
51 |
1/3✓ Branch 2 taken 188 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
188 | NoConstT* nobj = new ((void*)memory) NoConstT(*obj); |
52 | |||
53 | 188 | nobj->class_id = meta::type_id<NoConstT>(); | |
54 | 188 | nobj->parent = this; | |
55 | |||
56 | COZ_PROGRESS_NAMED("GCObject::copy"); | ||
57 | COZ_END("T::GCObject::copy"); | ||
58 | 188 | return nobj; | |
59 | } | ||
60 | |||
61 | //! Make an object match the lifetime of the parent | ||
62 | template <typename T> | ||
63 | void add_child(T* child) { | ||
64 |
1/2✓ Branch 1 taken 9905 times.
✗ Branch 2 not taken.
|
20688 | children.push_back(child); |
65 | 20688 | child->parent = this; | |
66 | 20688 | } | |
67 | |||
68 | template <typename T, typename D> | ||
69 | void add_child(Unique<T, D> child) { | ||
70 | GCObject* obj = child.release(); | ||
71 | add_child(obj); | ||
72 | } | ||
73 | |||
74 | void remove_child(GCObject* child, bool dofree); | ||
75 | |||
76 | void remove_child_if_parent(GCObject* child, bool dofree); | ||
77 | |||
78 | void move(GCObject* newparent) { | ||
79 |
1/2✓ Branch 0 taken 439 times.
✗ Branch 1 not taken.
|
439 | if (parent != nullptr) { |
80 | 439 | parent->remove_child(this, false); | |
81 | } | ||
82 | 439 | newparent->add_child(this); | |
83 | 439 | } | |
84 | |||
85 | static void free(GCObject* child); | ||
86 | |||
87 | void dump(std::ostream& out); | ||
88 | |||
89 | virtual ~GCObject(); | ||
90 | |||
91 | int class_id; | ||
92 | |||
93 | private: | ||
94 | void dump_recursive(std::ostream& out, Array<GCObject*>& visited, int prev, int depth); | ||
95 | |||
96 | template <typename T> | ||
97 | 10093 | static AllocatorCPU<T>& get_allocator() { | |
98 |
0/4✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
10093 | static auto alloc = AllocatorCPU<T>(); |
99 | 10093 | return alloc; | |
100 | } | ||
101 | |||
102 | protected: | ||
103 | Array<GCObject*> children; | ||
104 | |||
105 | GCObject* get_gc_parent() const { return parent; } | ||
106 | |||
107 | private: | ||
108 | GCObject* parent = nullptr; | ||
109 | |||
110 | static void private_free(GCObject* child); | ||
111 | }; | ||
112 | |||
113 | } // namespace lython | ||
114 | #endif | ||
115 |