#pragma once #include "gc-object.h" #include #include #include #include namespace effil { class GC { public: // global gc instance static GC& instance(); static sol::table exportAPI(sol::state_view& lua); // This method is used to create all managed objects. template ViewType create(Args&&... args) { if (enabled_ && count() >= step_ * lastCleanup_) collect(); std::unique_lock g(lock_); std::unique_ptr object(new ViewType); auto copy = *object; objects_.emplace(object->handle(), std::move(object)); g.unlock(); // We separate initialization out of construction cause the object under construction // should be added into GC before it will try to put any other objects into it's references copy.initialize(std::forward(args)...); return copy; } template ObjectType get(GCHandle handle) { std::lock_guard g(lock_); auto it = objects_.find(handle); assert(it != objects_.end()); auto result = dynamic_cast(it->second.get()); assert(result); return *result; } private: mutable std::mutex lock_; bool enabled_; std::atomic lastCleanup_; double step_; std::unordered_map> objects_; private: GC(); GC(GC&&) = delete; GC(const GC&) = delete; void collect(); void pause() { enabled_ = false; } void resume() { enabled_ = true; } double step() const { return step_; } void step(double newStep) { step_ = newStep; } bool enabled() { return enabled_; } size_t count() const; }; } // effil