62 lines
1.7 KiB
C++
62 lines
1.7 KiB
C++
#pragma once
|
|
|
|
// TODO: remove from here and from the project
|
|
#include <iostream>
|
|
|
|
#include "memory/freelist.hpp"
|
|
#include "memory/lazy_gc.hpp"
|
|
#include "threading/sync/spinlock.hpp"
|
|
#include "logging/default.hpp"
|
|
|
|
template <class T, class lock_t = SpinLock>
|
|
class SkiplistGC : public LazyGC<SkiplistGC<T, lock_t>, lock_t>
|
|
{
|
|
public:
|
|
SkiplistGC() : logger(logging::log->logger("SkiplistGC")) {}
|
|
|
|
// release_ref method should be called by a thread
|
|
// when the thread finish it job over object
|
|
// which has to be lazy cleaned
|
|
// if thread counter becames zero, all objects in the local_freelist
|
|
// are going to be deleted
|
|
// the only problem with this approach is that
|
|
// GC may never be called, but for now we can deal with that
|
|
void release_ref()
|
|
{
|
|
std::vector<T *> local_freelist;
|
|
|
|
// take freelist if there is no more threads
|
|
{
|
|
auto lock = this->acquire_unique();
|
|
assert(this->count > 0);
|
|
--this->count;
|
|
if (this->count == 0) {
|
|
freelist.swap(local_freelist);
|
|
}
|
|
}
|
|
|
|
if (local_freelist.size() > 0) {
|
|
logger.trace("GC started");
|
|
logger.trace("Local list size: {}", local_freelist.size());
|
|
long long counter = 0;
|
|
// destroy all elements from local_freelist
|
|
for (auto element : local_freelist) {
|
|
|
|
if (element->flags.is_marked()) {
|
|
T::destroy(element);
|
|
counter++;
|
|
}
|
|
}
|
|
logger.trace("Number of destroyed elements: {}", counter);
|
|
}
|
|
}
|
|
|
|
void collect(T *node) { freelist.add(node); }
|
|
|
|
protected:
|
|
Logger logger;
|
|
|
|
private:
|
|
FreeList<T> freelist;
|
|
};
|