source: src/Common/GC.h @ d318a18

new-env
Last change on this file since d318a18 was d318a18, checked in by Aaron Moss <a3moss@…>, 6 years ago

Fix assorted memory bugs with persistent-array environment

  • Property mode set to 100644
File size: 4.7 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// GC.h --
8//
9// Author           : Aaron B. Moss
10// Created On       : Thu Mar 15 14:47:00 2018
11// Last Modified By : Aaron B. Moss
12// Last Modified On : Thu Mar 15 14:47:00 2018
13// Update Count     : 1
14//
15
16#pragma once
17
18#include <cassert>
19#include <vector>
20
21class GC_Object;
22class BaseSyntaxNode;
23class GC_Guard;
24
25/// Manually traced and called garbage collector
26class GC {
27        friend class GcTracer;
28        friend class GC_Guard;
29
30        /// Collects the youngest generation, placing survivors in previous generation.
31        /// Young generation objects cannot be kept alive by pointers from older generation.
32        /// Older generation is used for subsequent new objects.
33        void collect_young();
34public:
35        /// Gets singleton GC instance
36        static GC& get();
37
38        /// Traces a traceable object
39        const GC& operator<< (const GC_Object*) const;
40
41        /// No-trace mark; returns true if the object exists and was not already marked
42        bool notrace_mark(const GC_Object*) const;
43
44        /// Adds a new object to garbage collection
45        void register_object(GC_Object*);
46
47        /// Adds an object to the set of static roots
48        void register_static_root(BaseSyntaxNode*);
49
50        /// Start new generation for subsequent new objects
51        GC_Guard new_generation();
52
53        /// Traces all static roots
54        void trace_static_roots();
55
56        /// Collects oldest generation; use oldest generation afterward.
57        /// Error if currently using younger generation
58        void collect();
59
60        /// Collects all contained objects
61        ~GC();
62
63private:
64        GC();
65
66        using Generation = std::vector<GC_Object*>;
67        std::vector<Generation> gens;  ///< Set of generations; always at least one
68
69        using StaticRoots = std::vector<BaseSyntaxNode*>;
70        StaticRoots static_roots;      ///< Set of static-lifetime roots
71
72        bool mark;                     ///< The current collection's mark bit
73        unsigned g;                    ///< The current number generation in use
74
75        /// Trace a traceable object (enabled by SFINAE)
76        template<typename T>
77        static inline auto do_trace(const GC& gc, T& obj, int) -> decltype(gc << obj, void()) {
78                gc << obj;
79        }
80
81        /// Do not trace an untraceable object
82        template<typename T>
83        static inline auto do_trace(const GC&, T&, long) -> void {}
84
85        /// Base case for maybe_trace
86        void maybe_trace() const {}
87
88public:
89        /// Trace any objects that are traceable
90        template<typename T, typename... Args>
91        void maybe_trace(T& obj, Args&... args) const {
92                // uses SFINAE trick to select proper overload; prefers actually tracing version
93                // (because of int->long conversion), but will fall back to non-tracing
94                do_trace(*this, obj, 0);
95                maybe_trace(args...);
96        }
97};
98
99/// Cleanup object for young generation
100class GC_Guard {
101        friend class GC;
102
103        GC& gc;      ///< GC associated with
104        unsigned g;  ///< Generation constructed for
105
106        GC_Guard( GC& gc, unsigned g ) : gc(gc), g(g) {}
107
108public:
109        ~GC_Guard() {
110                assert( gc.g == g && "collecting current generation" );
111                gc.collect_young();
112        }
113};
114
115/// Use young generation until next collection
116inline GC_Guard new_generation() { return GC::get().new_generation(); }
117
118// /// no-op default trace
119// template<typename T>
120// inline const GC& operator<< (const GC& gc, const T& x) { return gc; }
121
122inline void traceAll(const GC&) {}
123
124/// Marks all arguments as live in current generation
125template<typename T, typename... Args>
126inline void traceAll(const GC& gc, T& x, Args&... xs) {
127        gc << x;
128        traceAll(gc, xs...);
129}
130
131/// Traces roots without collecting
132template<typename... Args>
133inline void trace(Args&... roots) {
134        GC& gc = GC::get();
135        traceAll(gc, roots...);
136}
137
138/// Traces roots and collects other elements; should not be any young generations live
139template<typename... Args>
140inline void collect(Args&... roots) {
141        GC& gc = GC::get();
142        traceAll(gc, roots...);
143        gc.collect();
144}
145
146/// Makes a new expression as a static root
147template<typename T, typename... Args>
148inline T* new_static_root( Args&&... args ) {
149        T* root = new T( std::forward<Args>(args)... );
150        GC::get().register_static_root( root );
151        return root;
152}
153
154/// Class that is managed by the GC
155class GC_Object {
156        friend class GC;
157protected:
158        mutable bool mark;
159
160        // Override default constructors to ensure clones are registered and properly marked
161        GC_Object();
162
163        GC_Object(const GC_Object&);
164
165        GC_Object(GC_Object&&);
166
167        GC_Object& operator= (const GC_Object&) { /* do not assign mark */ return *this; }
168
169        GC_Object& operator= (GC_Object&&) { /* do not assign mark */ return *this; }
170
171        // Ensure subclasses can be deleted by garbage collector
172        virtual ~GC_Object() {}
173
174        /// override to trace any child objects
175        virtual void trace(const GC&) const {}
176};
177
178// Local Variables: //
179// tab-width: 4 //
180// mode: c++ //
181// compile-command: "make install" //
182// End: //
Note: See TracBrowser for help on using the repository browser.