#ifndef MRT_FINALIZER_PROCESSOR_H
#define MRT_FINALIZER_PROCESSOR_H
#include <climits>
#include <condition_variable>
#include <list>
#include <mutex>
#include "Base/Panic.h"
#include "Common/PageAllocator.h"
#include "Common/TypeDef.h"
#include "Heap/Collector/Collector.h"
namespace MapleRuntime {
#ifdef __APPLE__
template<typename T>
using ManagedList = std::list<T>;
#else
template<typename T>
using ManagedList = std::list<T, StdContainerAllocator<T, FINALIZER_PROCESSOR>>;
#endif
class FinalizerProcessor {
public:
FinalizerProcessor();
~FinalizerProcessor() = default;
U32 VisitFinalizers(const RootVisitor& visitor)
{
U32 count = 0;
std::lock_guard<std::mutex> l(listLock);
for (BaseObject*& obj : finalizers) {
visitor(reinterpret_cast<ObjectRef&>(obj));
++count;
}
return count;
}
void VisitGCRoots(const RootVisitor& visitor)
{
std::lock_guard<std::mutex> l(listLock);
for (BaseObject*& obj : finalizables) {
visitor(reinterpret_cast<ObjectRef&>(obj));
}
for (BaseObject*& obj : workingFinalizables) {
visitor(reinterpret_cast<ObjectRef&>(obj));
}
}
void VisitRawPointers(const RootVisitor& visitor)
{
std::lock_guard<std::mutex> l(listLock);
for (BaseObject*& obj : finalizables) {
visitor(reinterpret_cast<ObjectRef&>(obj));
}
for (BaseObject*& obj : workingFinalizables) {
visitor(reinterpret_cast<ObjectRef&>(obj));
}
for (BaseObject*& obj : finalizers) {
visitor(reinterpret_cast<ObjectRef&>(obj));
}
}
void Notify();
void WaitStarted();
void Start();
void Stop();
void Run();
void Init();
void Fini();
void WaitStop();
void EnqueueFinalizables(const std::function<bool(BaseObject*)>& finalizable, U32 countLimit = UINT_MAX);
void RegisterFinalizer(BaseObject* obj);
bool IsRunning() const { return running; }
uint32_t GetTid() const { return tid; }
Mutator* GetMutator() const { return fpMutator; }
void NotifyToReclaimGarbage() { shouldReclaimHeapGarbage.store(true); }
void NotifyToFeedAllocBuffers()
{
shouldFeedHungryBuffers.store(true, std::memory_order_release);
Notify();
}
private:
void InitFinalizerCJThread();
void NotifyStarted();
void Wait(U32 timeoutMilliSeconds);
void ProcessFinalizables();
void ProcessFinalizableList();
void ReclaimHeapGarbage();
void FeedHungryBuffers();
std::mutex wakeLock;
std::condition_variable wakeCondition;
std::mutex startedLock;
std::condition_variable startedCondition;
volatile bool started;
volatile bool running;
U32 iterationWaitTime;
std::mutex listLock;
ManagedList<BaseObject*> finalizers;
ManagedList<BaseObject*> finalizables;
ManagedList<BaseObject*> workingFinalizables;
std::atomic<bool> hasFinalizableJob;
std::atomic<bool> shouldReclaimHeapGarbage;
std::atomic<bool> shouldFeedHungryBuffers;
#if defined(MRT_DEBUG) && (MRT_DEBUG == 1)
void LogAfterProcess();
#endif
uint64_t timeProcessorBegin;
uint64_t timeProcessUsed;
uint64_t timeCurrentProcessBegin;
uint32_t tid = 0;
pthread_t threadHandle = 0;
Mutator* fpMutator = nullptr;
bool finalizerCJThreadInitialized = false;
};
}
#endif