effil/src/cpp/garbage-collector.h
mihacooper b3380a7879
Fix raise condition in GC objects construction (#154)
* Fix raise condition in GC objects construction

* review fixes
2020-09-19 19:53:07 +03:00

69 lines
1.8 KiB
C++

#pragma once
#include "gc-object.h"
#include <sol.hpp>
#include <mutex>
#include <unordered_map>
#include <unordered_set>
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 <typename ViewType, typename... Args>
ViewType create(Args&&... args) {
if (enabled_ && count() >= step_ * lastCleanup_)
collect();
std::unique_lock<std::mutex> g(lock_);
std::unique_ptr<ViewType> 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>(args)...);
return copy;
}
template <typename ObjectType>
ObjectType get(GCHandle handle) {
std::lock_guard<std::mutex> g(lock_);
auto it = objects_.find(handle);
assert(it != objects_.end());
auto result = dynamic_cast<ObjectType*>(it->second.get());
assert(result);
return *result;
}
private:
mutable std::mutex lock_;
bool enabled_;
std::atomic<uint64_t> lastCleanup_;
double step_;
std::unordered_map<GCHandle, std::unique_ptr<BaseGCObject>> 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