1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-19 08:30:25 +02:00
Beef/BeefLibs/corlib/src/GC.bf

201 lines
5.3 KiB
Beef
Raw Normal View History

2019-08-23 11:56:54 -07:00
using System;
using System.Threading;
namespace System
{
public interface ILeakIdentifiable
{
void ToLeakString(String str);
}
#if BF_ENABLE_REALTIME_LEAK_CHECK || BF_DEBUG_ALLOC
[AlwaysInclude]
#endif
public static class GC
{
enum RootResult
{
Ok
}
public delegate Result<void> RootCallback();
#if BF_ENABLE_REALTIME_LEAK_CHECK
static Event<RootCallback> sRootCallbacks ~ _.Dispose();
static Thread sThread;
static Monitor sMonitor = new Monitor() ~ delete _;
static this()
{
FindAllTLSMembers();
Init();
}
static ~this()
{
StopCollecting();
}
#elif BF_DEBUG_ALLOC
static ~this()
{
//Report();
}
#endif
public static void AddRootCallback(RootCallback rootDelegate)
{
#if BF_ENABLE_REALTIME_LEAK_CHECK
using (sMonitor.Enter())
sRootCallbacks.Add(rootDelegate);
#endif
}
public static void RemoveRootCallback(RootCallback rootDelegate)
{
#if BF_ENABLE_REALTIME_LEAK_CHECK
using (sMonitor.Enter())
sRootCallbacks.Remove(rootDelegate);
#endif
}
static bool CallRootCallbacks()
{
#if BF_ENABLE_REALTIME_LEAK_CHECK
using (sMonitor.Enter())
{
var result = sRootCallbacks();
if (result case .Err)
return false;
}
#endif
return true;
}
[CallingConvention(.Cdecl)]
2019-08-23 11:56:54 -07:00
extern static void ReportTLSMember(int moduleTLSIndex, void* addr, void* markFunc);
static void ReportTLSMember(void* addr, void* markFunc)
{
ReportTLSMember(Thread.ModuleTLSIndex, addr, markFunc);
}
extern static void Run();
static void ThreadProc(Object param)
{
Run();
}
public static void Start()
{
#if BF_ENABLE_REALTIME_LEAK_CHECK
sThread = new Thread(new => ThreadProc);
sThread.Start(true);
#endif
}
#if BF_ENABLE_REALTIME_LEAK_CHECK || BF_DEBUG_ALLOC
[CallingConvention(.Cdecl)]
2019-08-23 11:56:54 -07:00
public extern static void Report();
[CallingConvention(.Cdecl)]
2019-08-23 11:56:54 -07:00
public extern static void Shutdown();
[CallingConvention(.Cdecl)]
2019-08-23 11:56:54 -07:00
public extern static void SetMaxRawDeferredObjectFreePercentage(int maxPercentage);
#else
public static void Report() {}
public static void Shutdown() {}
public static void SetMaxRawDeferredObjectFreePercentage(int maxPercentage) {}
#endif
#if BF_ENABLE_REALTIME_LEAK_CHECK
[CallingConvention(.Cdecl)]
2019-08-23 11:56:54 -07:00
private extern static void Init();
[CallingConvention(.Cdecl)]
2019-08-23 11:56:54 -07:00
public extern static void Collect(bool async = true);
[CallingConvention(.Cdecl)]
2019-08-23 11:56:54 -07:00
private extern static void StopCollecting();
[CallingConvention(.Cdecl)]
2019-08-23 11:56:54 -07:00
private extern static void AddStackMarkableObject(Object obj);
[CallingConvention(.Cdecl)]
2019-08-23 11:56:54 -07:00
private extern static void RemoveStackMarkableObject(Object obj);
[CallingConvention(.Cdecl), AlwaysInclude]
2019-08-23 11:56:54 -07:00
private extern static void MarkAllStaticMembers();
[CallingConvention(.Cdecl)]
2019-08-23 11:56:54 -07:00
private extern static void FindAllTLSMembers();
[CallingConvention(.Cdecl)]
2019-08-23 11:56:54 -07:00
public extern static void DebugDumpLeaks();
[CallingConvention(.Cdecl)]
2019-08-23 11:56:54 -07:00
public extern static void Mark(Object obj);
[CallingConvention(.Cdecl)]
2019-08-23 11:56:54 -07:00
public extern static void Mark(void* ptr, int size);
[CallingConvention(.Cdecl)]
2020-06-16 10:21:37 -07:00
public extern static void SetAutoCollectPeriod(int periodMS); // <= -1 to disable, 0 to constantly run. Defaults to 2000.
[CallingConvention(.Cdecl)]
2019-08-23 11:56:54 -07:00
public extern static void SetCollectFreeThreshold(int freeBytes); // -1 to disable, 0 to trigger collection after every single free. Defaults to 64MB
[CallingConvention(.Cdecl)]
2019-08-23 11:56:54 -07:00
public extern static void SetMaxPausePercentage(int maxPausePercentage); // 0 = disabled. Defaults to 20.
[CallingConvention(.Cdecl)]
extern static void AddPendingThread(void* internalThread);
2019-08-23 11:56:54 -07:00
#else
public static void Collect(bool async = true) {}
private static void MarkAllStaticMembers() {}
public static void DebugDumpLeaks() {}
2019-10-29 05:01:04 -07:00
[SkipCall]
public static void Mark(Object obj) {}
2019-08-23 11:56:54 -07:00
public static void Mark(void* ptr, int size) {}
public static void SetAutoCollectPeriod(int periodMS) {}
public static void SetCollectFreeThreshold(int freeBytes) {}
public static void SetMaxPausePercentage(int maxPausePercentage) {}
2020-08-31 11:33:11 -07:00
static void AddPendingThread(void* internalThreadInfo) {}
2019-08-23 11:56:54 -07:00
#endif
static void MarkDerefedObject(Object* obj)
{
#if BF_ENABLE_REALTIME_LEAK_CHECK
Mark(*obj);
#endif
}
public static mixin Mark<T>(T val) where T : class
{
2019-08-23 11:56:54 -07:00
#if BF_ENABLE_REALTIME_LEAK_CHECK
Mark((Object)val);
2019-08-23 11:56:54 -07:00
#endif
}
public static mixin Mark<T>(T val) where T : struct
{
2019-08-23 11:56:54 -07:00
#if BF_ENABLE_REALTIME_LEAK_CHECK
val.[Friend]GCMarkMembers();
2019-08-23 11:56:54 -07:00
#endif
}
public static mixin Mark<T>(T val) where T : struct*
{
// Memory pointed to by struct*'s will already-scanned stack memory,
// or the memory would already be registered with the GC
2019-08-23 11:56:54 -07:00
}
public static mixin Mark<TSizedArray, T, Size>(TSizedArray val) where Size : const int where TSizedArray : SizedArray<T, Size>
2019-08-23 11:56:54 -07:00
{
#if BF_ENABLE_REALTIME_LEAK_CHECK
for (var element in val)
{
Mark(element);
}
#endif
}
public static void ToLeakString(Object obj, String strBuffer)
{
obj.GetType().GetName(strBuffer);
/*strBuffer.Append("@");
((intptr)(void*)obj).ToString(strBuffer, "X", null);
var leakIdentifier = obj as ILeakIdentifiable;
if (leakIdentifier != null)
{
strBuffer.Append(" : ");
leakIdentifier.ToLeakString(strBuffer);
}*/
}
}
}