CoroutineLeakCheck

This commit is contained in:
Krzosa Karol
2026-01-19 09:08:26 +01:00
parent 372287f557
commit 1ce128a5d5
5 changed files with 65 additions and 32 deletions

View File

@@ -47,6 +47,7 @@ struct BlockArena {
U8 *end;
BlockArenaNode *blocks;
Allocator allocator;
int refs; // :CoroutineLeakCheck
operator Allocator() { return {BlockArenaAllocatorProc, this}; }
};
@@ -66,6 +67,7 @@ struct VirtualArena {
size_t reserve;
size_t commit;
size_t align;
int refs; // :CoroutineLeakCheck
operator Allocator() {
void *ArenaAllocatorProc(void *object, int kind, void *p, size_t size);
@@ -112,28 +114,32 @@ API VirtualArena *GetScratchEx(VirtualArena **conflicts, int conflict_count);
struct Scratch {
VirtualArena *arena;
U64 p;
Scratch() {arena = &ScratchArenas[0]; p = arena->len;}
Scratch() {arena = &ScratchArenas[0]; p = arena->len; arena->refs += 1;}
Scratch(VirtualArena *conflict) {
VirtualArena *conf[] = {conflict};
arena = GetScratchEx(conf, Lengthof(conf));
p = arena->len;
arena->refs += 1;
}
Scratch(VirtualArena *c1, VirtualArena *c2) {
VirtualArena *conf[] = {c1, c2};
arena = GetScratchEx(conf, Lengthof(conf));
p = arena->len;
arena->refs += 1;
}
Scratch(Allocator conflict) {
VirtualArena *conf[] = {(VirtualArena *)conflict.object};
arena = GetScratchEx(conf, Lengthof(conf));
p = arena->len;
arena->refs += 1;
}
Scratch(Allocator c1, Allocator c2) {
VirtualArena *conf[] = {(VirtualArena *)c1.object, (VirtualArena *)c2.object};
arena = GetScratchEx(conf, Lengthof(conf));
p = arena->len;
arena->refs += 1;
}
~Scratch() { SetLen(arena, p); }
~Scratch() { SetLen(arena, p); arena->refs -= 1; }
operator VirtualArena *() { return arena; }
operator Allocator() { return *arena; }

View File

@@ -62,6 +62,16 @@ void CoUpdate(Event *event) {
}
}
#if DEBUG_BUILD
//:CoroutineLeakCheck
// Make sure we don't leak scratch arenas between coroutine boundaries.
// it leads to memory corruption! If you hit Assert here make sure you
// don't leak the scratch arena.
for (int i = 0; i < Lengthof(ScratchArenas); i += 1) {
Assert(ScratchArenas[i].refs == 0);
}
#endif
double took = GetTimeSeconds() - start;
if (took > (0.016666 / 3.0)) {
break;

View File

@@ -472,35 +472,32 @@ inline void AddEvent(Array<Event> *events, Event ev) {
Add(events, ev);
}
Array<Event> GetEventsForFrame(Allocator allocator) {
void GetEventsForFrame(Array<Event> *events) {
ProfileFunction();
Array<Event> result = {allocator};
if (EventPlayback.len) {
result = TightCopy(allocator, EventPlayback);
EventPlayback.len = 0;
For (EventPlayback) {
Add(events, it);
}
SDL_Event event;
if (WaitForEventsState) {
SDL_WaitEvent(&event);
Event ev = TranslateSDLEvent(&event);
AddEvent(&result, ev);
AddEvent(events, ev);
}
while (SDL_PollEvent(&event)) {
Event ev = TranslateSDLEvent(&event);
AddEvent(&result, ev);
AddEvent(events, ev);
}
if (result.len == 0) {
if (events->len == 0) {
Event event = {};
FillEventWithBasicData(&event);
event.kind = EVENT_UPDATE;
Add(&result, event);
Add(events, event);
}
Assert(result.len);
return result;
Assert(events->len);
}

View File

@@ -68,3 +68,17 @@ void CMD_SetProjectHere() {
}
#endif
} RegisterCommand(CMD_SetProjectHere, "", "Sets the project directory, opens the project file etc.");
void CO_CreateProject(mco_coro *co) {
String16 project_name16 = QueryUserString(co, "Please tell me, how would you like to name your project?");
String directory = GetPrimaryDirectory();
{
Scratch scratch;
String project_name = ToString(scratch, project_name16);
String name = Format(scratch, "%S/%S", directory, project_name);
MakeDir(name);
Open(name);
}
} RegisterCoroutineCommand(CO_CreateProject, "", "Creates a project in current buffer directory with template files and all that, asks user for input etc.");

View File

@@ -626,6 +626,7 @@ void Update(Event event) {
ProfileFunction();
LayoutWindows(event.xwindow, event.ywindow);
{
Scratch scratch;
Array<Window *> order = GetWindowZOrder(scratch);
For(order) {
@@ -636,6 +637,7 @@ void Update(Event event) {
view->main_caret_on_begin_frame = view->carets[0];
view->update_scroll = true;
}
}
For (Windows) {
if (it->jump_history) {
@@ -670,7 +672,7 @@ void Update(Event event) {
CoUpdate(&event);
For(IterateInReverse(&order)) {
For (Windows) {
if (!it->visible) continue;
View *view = GetView(it->active_view);
UpdateScroll(it, !AreEqual(view->main_caret_on_begin_frame, view->carets[0]) && view->update_scroll);
@@ -783,13 +785,13 @@ void Update(Event event) {
GarbageCollect();
}
Array<Event> FrameEvents;
void MainLoop() {
ProfileFunction();
Scratch scratch;
FrameID += 1;
Array<Event> frame_events = GetEventsForFrame(scratch);
For(frame_events) {
FrameEvents.len = 0;
GetEventsForFrame(&FrameEvents);
For (FrameEvents) {
#if PLUGIN_RECORD_EVENTS
if (it.kind != EVENT_UPDATE && !Testing) {
Serialize(EventBuffer, &it);
@@ -823,6 +825,7 @@ void MainLoop() {
// This shouldn't matter to the state of the program, only appearance for
// the user
{
Scratch scratch;
ProfileScope(SetWindowTitle);
Window *window = GetActiveWind();
View *view = GetView(window->active_view);
@@ -832,15 +835,18 @@ void MainLoop() {
SDL_SetWindowTitle(SDLWindow, string.data);
}
Event *event = GetLast(frame_events);
Event *event = GetLast(FrameEvents);
SetMouseCursor(*event);
LayoutWindows(event->xwindow, event->ywindow); // This is here to render changes in title bar size without a frame of delay
BeginFrameRender(event->xwindow, event->ywindow);
{
Scratch scratch;
Array<Window *> order = GetWindowZOrder(scratch);
For(IterateInReverse(&order)) {
if (!it->visible) continue;
DrawWindow(it, *GetLast(frame_events));
DrawWindow(it, *GetLast(FrameEvents));
}
}
EndFrameRender(event->xwindow, event->ywindow, BackgroundColor);
SDL_GL_SwapWindow(SDLWindow);