// // Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo // // The contents of this file are covered under the licence agreement in the // file "LICENCE" distributed with Cforall. // // GC.h -- // // Author : Aaron B. Moss // Created On : Thu Mar 15 14:47:00 2018 // Last Modified By : Aaron B. Moss // Last Modified On : Thu Mar 15 14:47:00 2018 // Update Count : 1 // #pragma once #include #include class GC_Object; class BaseSyntaxNode; class GC_Guard; /// Manually traced and called garbage collector class GC { friend class GcTracer; friend class GC_Guard; /// Collects the youngest generation, placing survivors in previous generation. /// Young generation objects cannot be kept alive by pointers from older generation. /// Older generation is used for subsequent new objects. void collect_young(); public: /// Gets singleton GC instance static GC& get(); /// Traces a traceable object const GC& operator<< (const GC_Object*) const; /// Adds a new object to garbage collection void register_object(GC_Object*); /// Adds an object to the set of static roots void register_static_root(BaseSyntaxNode*); /// Start new generation for subsequent new objects GC_Guard new_generation(); /// Traces all static roots void trace_static_roots(); /// Collects oldest generation; use oldest generation afterward. /// Error if currently using younger generation void collect(); /// Collects all contained objects ~GC(); private: GC(); using Generation = std::vector; std::vector gens; ///< Set of generations; always at least one using StaticRoots = std::vector; StaticRoots static_roots; ///< Set of static-lifetime roots bool mark; ///< The current collection's mark bit unsigned g; ///< The current number generation in use }; /// Cleanup object for young generation class GC_Guard { friend class GC; GC& gc; ///< GC associated with unsigned g; ///< Generation constructed for GC_Guard( GC& gc, unsigned g ) : gc(gc), g(g) {} public: ~GC_Guard() { assert( gc.g == g && "collecting current generation" ); gc.collect_young(); } }; /// Use young generation until next collection inline GC_Guard new_generation() { return GC::get().new_generation(); } // /// no-op default trace // template // inline const GC& operator<< (const GC& gc, const T& x) { return gc; } inline void traceAll(const GC&) {} /// Marks all arguments as live in current generation template inline void traceAll(const GC& gc, T& x, Args&... xs) { gc << x; traceAll(gc, xs...); } /// Traces roots without collecting template inline void trace(Args&... roots) { GC& gc = GC::get(); traceAll(gc, roots...); } /// Traces roots and collects other elements; should not be any young generations live template inline void collect(Args&... roots) { GC& gc = GC::get(); traceAll(gc, roots...); gc.collect(); } /// Makes a new expression as a static root template inline T* new_static_root( Args&&... args ) { T* root = new T( std::forward(args)... ); GC::get().register_static_root( root ); return root; } /// Class that is managed by the GC class GC_Object { friend class GC; protected: mutable bool mark; // Override default constructors to ensure clones are registered and properly marked GC_Object(); GC_Object(const GC_Object&); GC_Object(GC_Object&&); GC_Object& operator= (const GC_Object&) { /* do not assign mark */ return *this; } GC_Object& operator= (GC_Object&&) { /* do not assign mark */ return *this; } // Ensure subclasses can be deleted by garbage collector virtual ~GC_Object() {} /// override to trace any child objects virtual void trace(const GC&) const {} }; // Local Variables: // // tab-width: 4 // // mode: c++ // // compile-command: "make install" // // End: //