Skip to content

Instantly share code, notes, and snippets.

@Fuyutsubaki
Created January 17, 2014 16:03
Show Gist options
  • Save Fuyutsubaki/8475949 to your computer and use it in GitHub Desktop.
Save Fuyutsubaki/8475949 to your computer and use it in GitHub Desktop.
Mini Garbage Collection on C++ 小さなガベージコレクション
#pragma once
#include<memory>
#include<unordered_map>
#include<initializer_list>
#include<type_traits>
/*
**sample**
struct A
{
A*p = nullptr;
~A(){std::cout << "~A()";}
};
int main()
{
struct PtrGeter
{
std::vector<A*>operator()(A*p){return{ p->p };}
};
unique_ptr_Holder<A, PtrGeter> gc;
auto a=gc.grip(std::make_unique<A>());
auto b=gc.grip(std::make_unique<A>());
auto c=gc.grip(std::make_unique<A>());
a->p = b;
gc.sweep({ a }); //a&b alive ,c dead
std::cout << "GC";
} //a,b dead
*/
template<class T,class UsingPointerGeter>
class unique_ptr_Holder
{
template<class U>
using Check_base_type = typename std::enable_if<std::is_base_of<T, U>::value>::type*&;
public:
template<class U, class =Check_base_type<U>>
U*grip(std::unique_ptr<U>&&ptr)
{
auto row = ptr.get();
ptr_s_.emplace(row, Object(std::move(ptr)));
return row;
}
void sweep(const std::initializer_list<T*>&list)
{
for (auto&val : ptr_s_)
val.second.flag = false;
for (auto p : list)
sweep_impl(p);
for (auto it = ptr_s_.begin(); it != ptr_s_.end();)
{
if (!it->second.flag)
ptr_s_.erase(it++);
else
++it;
}
}
void clear(){ptr_s_.clear();}
private:
struct Object
{
Object(std::unique_ptr<T>&&ptr)
:ptr(std::move(ptr))
{}
Object(){}
Object(Object&&obj)
:ptr(std::move(obj.ptr)), flag(flag)
{}
bool flag=false;
std::unique_ptr<T> ptr;
};
using Map_type = std::unordered_map<void*, Object>;
Map_type ptr_s_;
UsingPointerGeter GetPtr_;
void sweep_impl(T* ptr)
{
if (ptr == nullptr)return;
auto &val = ptr_s_.at(ptr);
if (val.flag)return;
val.flag = true;
for (const auto &p : GetPtr_(ptr))
sweep_impl(p);
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment