CoroutineLeakCheck
This commit is contained in:
@@ -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; }
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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.");
|
||||
@@ -626,15 +626,17 @@ void Update(Event event) {
|
||||
ProfileFunction();
|
||||
LayoutWindows(event.xwindow, event.ywindow);
|
||||
|
||||
Scratch scratch;
|
||||
Array<Window *> order = GetWindowZOrder(scratch);
|
||||
For(order) {
|
||||
if (!it->visible) {
|
||||
continue;
|
||||
{
|
||||
Scratch scratch;
|
||||
Array<Window *> order = GetWindowZOrder(scratch);
|
||||
For(order) {
|
||||
if (!it->visible) {
|
||||
continue;
|
||||
}
|
||||
View *view = GetView(it->active_view);
|
||||
view->main_caret_on_begin_frame = view->carets[0];
|
||||
view->update_scroll = true;
|
||||
}
|
||||
View *view = GetView(it->active_view);
|
||||
view->main_caret_on_begin_frame = view->carets[0];
|
||||
view->update_scroll = true;
|
||||
}
|
||||
|
||||
For (Windows) {
|
||||
@@ -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);
|
||||
|
||||
Array<Window *> order = GetWindowZOrder(scratch);
|
||||
For(IterateInReverse(&order)) {
|
||||
if (!it->visible) continue;
|
||||
DrawWindow(it, *GetLast(frame_events));
|
||||
{
|
||||
Scratch scratch;
|
||||
Array<Window *> order = GetWindowZOrder(scratch);
|
||||
For(IterateInReverse(&order)) {
|
||||
if (!it->visible) continue;
|
||||
DrawWindow(it, *GetLast(FrameEvents));
|
||||
}
|
||||
}
|
||||
EndFrameRender(event->xwindow, event->ywindow, BackgroundColor);
|
||||
SDL_GL_SwapWindow(SDLWindow);
|
||||
|
||||
Reference in New Issue
Block a user