effil/src/cpp/garbage-collector.h
mihacooper 5057116136 Channels implementation and tests (#42)
Channel implementation
2017-04-16 22:58:21 +03:00

89 lines
2.4 KiB
C++

#pragma once
#include "spin-mutex.h"
#include <sol.hpp>
#include <mutex>
#include <map>
#include <set>
namespace effil {
// Unique handle for all objects spawned from one object.
typedef void* GCObjectHandle;
static const GCObjectHandle GCNull = nullptr;
// All effil objects that owned in lua code have to inherit this class.
// This type o object can persist in multiple threads and in multiple lua states.
// Child has to care about storing data and concurrent access.
class GCObject {
public:
GCObject() noexcept
: refs_(new std::set<GCObjectHandle>) {}
GCObject(const GCObject& init) = default;
GCObject(GCObject&& init) = default;
virtual ~GCObject() = default;
GCObjectHandle handle() const noexcept { return reinterpret_cast<GCObjectHandle>(refs_.get()); }
size_t instances() const noexcept { return refs_.use_count(); }
const std::set<GCObjectHandle>& refers() const { return *refs_; }
protected:
std::shared_ptr<std::set<GCObjectHandle>> refs_;
};
class GC {
public:
GC();
~GC() = default;
// This method is used to create all managed objects.
template <typename ObjectType, typename... Args>
ObjectType create(Args&&... args) {
if (enabled_ && lastCleanup_.fetch_add(1) == step_)
collect();
auto object = std::make_shared<ObjectType>(std::forward<Args>(args)...);
std::lock_guard<std::mutex> g(lock_);
objects_[object->handle()] = object;
return *object;
}
template <typename ObjectType>
ObjectType get(GCObjectHandle handle) {
std::lock_guard<std::mutex> g(lock_);
// TODO: add dynamic cast to check?
return *static_cast<ObjectType*>(findObject(handle));
}
bool has(GCObjectHandle handle) const;
void collect();
size_t size() const;
void pause() { enabled_ = false; };
void resume() { enabled_ = true; };
size_t step() const { return step_; }
void step(size_t newStep) { step_ = newStep; }
bool enabled() { return enabled_; };
size_t count();
static GC& instance();
static sol::table getLuaApi(sol::state_view& lua);
private:
mutable std::mutex lock_;
bool enabled_;
std::atomic<size_t> lastCleanup_;
size_t step_;
std::map<GCObjectHandle, std::shared_ptr<GCObject>> objects_;
private:
GCObject* findObject(GCObjectHandle handle);
private:
GC(GC&&) = delete;
GC(const GC&) = delete;
};
} // effil