#pragma once #include #include #include #include #include #ifndef __AQ_USE_THREADEDGC__ class GC { private: template using vector = vector_type; template using tuple = std::tuple; size_t current_size = 0, max_size, interval, forced_clean, forceclean_timer = 0; bool running, alive; // ptr, dealloc, ref, sz vector> *q, *q_back; std::thread handle; std::atomic lock; // maybe use volatile std::thread::id instead protected: void acquire_lock() { auto this_pid = std::this_thread::get_id(); while(lock != this_pid) { while(lock != this_pid && lock != std::thread::id()) { std::this_thread::sleep_for(std::chrono::milliseconds(0)); } lock = this_pid; } } void release_lock(){ lock = std::thread::id(); } void gc() { if (q->size == 0) return; auto t = q; acquire_lock(); q = q_back; release_lock(); for(const auto& t : *t) { std::get<1>(t)(std::get<0>(t)); } t->clear(); q_back = t; running = false; current_size = 0; } void daemon() { using namespace std::chrono; while (alive) { if (running) { if (current_size > max_size || forceclean_timer > forced_clean) { gc(); forceclean_timer = 0; } std::this_thread::sleep_for(microseconds(interval)); forceclean_timer += interval; } else { std::this_thread::sleep_for(10ms); forceclean_timer += 10000; } } } void start_deamon() { q = new vector>(); q_back = new vector>(); lock = thread::id(); alive = true; handle = std::thread(&daemon); } void terminate_daemon() { running = false; alive = false; delete q; delete q_back; using namespace std::chrono; if (handle.joinable()) { std::this_thread::sleep_for(microseconds(1000 + std::max(static_cast(10000), interval))); handle.join(); } } public: void reg(void* v, uint32_t sz = 1, void(*f)(void*) = [](void* v) {free (v); } ) { acquire_lock(); current_size += sz; q.push_back({ v, f }); running = true; release_lock() } GC( uint32_t max_size = 0xfffffff, uint32_t interval = 10000, uint32_t forced_clean = 1000000 //one seconds ) : max_size(max_size), interval(interval), forced_clean(forced_clean){ start_deamon(); } // 256 MB ~GC(){ terminate_daemon(); } }; #else class GC { public: GC(uint32_t) = default; void reg( void* v, uint32_t = 0, void(*f)(void*) = [](void* v) {free (v); } ) const { f(v); } } #endif