Implemented a basic event log, and used it in various places around the codebase. Also removed foldhaus_memory as it isn't being used
This commit is contained in:
parent
305afc65cd
commit
05e6a191e8
|
@ -330,7 +330,7 @@ ParseVector(tokenizer* T, v3* Value)
|
|||
return Result;
|
||||
}
|
||||
|
||||
// TODO(Peter): Error reporting
|
||||
// TODO(Peter): :ErrorLogging
|
||||
#define ParseLEDStripToken(tokenizer, parse_expr, error_msg) \
|
||||
(parse_expr) && (ParseComma(tokenizer))
|
||||
|
||||
|
@ -388,7 +388,7 @@ ParseLEDStrip (led_strip_definition* Strip, tokenizer* T, memory_arena* Arena)
|
|||
}
|
||||
|
||||
internal assembly_definition
|
||||
ParseAssemblyFile (u8* FileBase, s32 FileSize, memory_arena* Arena)
|
||||
ParseAssemblyFile (u8* FileBase, s32 FileSize, memory_arena* Arena, event_log* EventLog)
|
||||
{
|
||||
assembly_definition Assembly = {};
|
||||
|
||||
|
@ -415,7 +415,8 @@ ParseAssemblyFile (u8* FileBase, s32 FileSize, memory_arena* Arena)
|
|||
}
|
||||
else
|
||||
{
|
||||
InvalidCodePath;
|
||||
LogError(EventLog, "Unable to parse LED strip in assembly file");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -426,14 +427,15 @@ ParseAssemblyFile (u8* FileBase, s32 FileSize, memory_arena* Arena)
|
|||
}
|
||||
else
|
||||
{
|
||||
InvalidCodePath;
|
||||
LogError(EventLog, "Did not find ent of file identifier in assembly file");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO(Peter): Error reporting
|
||||
// TODO(Peter): :ErrorLoggong
|
||||
InvalidCodePath;
|
||||
}
|
||||
|
||||
|
|
|
@ -81,6 +81,9 @@ INITIALIZE_APPLICATION(InitializeApplication)
|
|||
State->Transient.Alloc = (gs_memory_alloc*)Context.PlatformAlloc;
|
||||
State->Transient.Realloc = (gs_memory_realloc*)Context.PlatformRealloc;
|
||||
|
||||
State->GlobalLog = PushStruct(&State->Transient, event_log);
|
||||
*State->GlobalLog = {0};
|
||||
|
||||
s32 CommandQueueSize = 32;
|
||||
command_queue_entry* CommandQueueMemory = PushArray(&State->Permanent,
|
||||
command_queue_entry,
|
||||
|
@ -143,7 +146,7 @@ INITIALIZE_APPLICATION(InitializeApplication)
|
|||
}
|
||||
else
|
||||
{
|
||||
// TODO(Peter): How do we want to handle not having a font?
|
||||
LogError(State->GlobalLog, "Unable to load font");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#include "../meta/gs_meta_lexer.h"
|
||||
|
||||
#include "../gs_libs/gs_font.h"
|
||||
#include "foldhaus_log.h"
|
||||
|
||||
#include "interface.h"
|
||||
|
||||
#include "foldhaus_network_ordering.h"
|
||||
|
@ -84,6 +86,8 @@ struct app_state
|
|||
panel* HotPanel;
|
||||
|
||||
pattern_node_workspace NodeWorkspace;
|
||||
|
||||
event_log* GlobalLog;
|
||||
};
|
||||
|
||||
internal void OpenColorPicker(app_state* State, v4* Address);
|
||||
|
|
|
@ -70,10 +70,10 @@ s32 TempAssemblyOffsetsCount = 3;
|
|||
internal void
|
||||
LoadAssembly (app_state* State, context Context, char* Path)
|
||||
{
|
||||
platform_memory_result TestAssemblyFile = Context.PlatformReadEntireFile(Path);
|
||||
if (TestAssemblyFile.Error == PlatformMemory_NoError)
|
||||
platform_memory_result AssemblyFile = Context.PlatformReadEntireFile(Path);
|
||||
if (AssemblyFile.Error == PlatformMemory_NoError)
|
||||
{
|
||||
assembly_definition AssemblyDefinition = ParseAssemblyFile(TestAssemblyFile.Base, TestAssemblyFile.Size, &State->Transient);
|
||||
assembly_definition AssemblyDefinition = ParseAssemblyFile(AssemblyFile.Base, AssemblyFile.Size, &State->Transient, State->GlobalLog);
|
||||
|
||||
string PathString = MakeStringLiteral(Path);
|
||||
s32 IndexOfLastSlash = FastLastIndexOfCharInCharArray(PathString.Memory, PathString.Length, '\\');
|
||||
|
@ -91,11 +91,11 @@ LoadAssembly (app_state* State, context Context, char* Path)
|
|||
State->ActiveAssemblyIndecies.PushElementOnList(NewAssemblyHandle);
|
||||
State->TotalLEDsCount += NewAssembly.LEDCount;
|
||||
|
||||
Context.PlatformFree(TestAssemblyFile.Base, TestAssemblyFile.Size);
|
||||
Context.PlatformFree(AssemblyFile.Base, AssemblyFile.Size);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO(Peter): :ErrorLogging
|
||||
LogError(State->GlobalLog, "Unable to load assembly file");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
//
|
||||
// File: foldhaus_log.h
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2020-02-05
|
||||
//
|
||||
#ifndef FOLDHAUS_LOG_H
|
||||
|
||||
enum log_entry_type
|
||||
{
|
||||
LogEntry_Message,
|
||||
LogEntry_Error,
|
||||
};
|
||||
|
||||
struct log_entry
|
||||
{
|
||||
string Message;
|
||||
log_entry_type Type;
|
||||
};
|
||||
|
||||
#define LOG_ENTRIES_MAX 256
|
||||
struct event_log
|
||||
{
|
||||
log_entry Entries[LOG_ENTRIES_MAX];
|
||||
// Circular buffer head position
|
||||
u32 NextEntry;
|
||||
};
|
||||
|
||||
#define LogMessage(_Log, _Message) PushLogEntry(_Log, MakeStringLiteral(_Message), LogEntry_Message)
|
||||
#define LogError(_Log, _Message) PushLogEntry(_Log, MakeStringLiteral(_Message), LogEntry_Error)
|
||||
|
||||
internal void
|
||||
PushLogEntry(event_log* Log, string Message, log_entry_type Type)
|
||||
{
|
||||
u32 NewLogIndex = Log->NextEntry++;
|
||||
if (Log->NextEntry >= LOG_ENTRIES_MAX)
|
||||
{
|
||||
Log->NextEntry = 0;
|
||||
}
|
||||
|
||||
log_entry* NewEntry = Log->Entries + NewLogIndex;
|
||||
NewEntry->Message = Message;
|
||||
NewEntry->Type = Type;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define FOLDHAUS_LOG_H
|
||||
#endif // FOLDHAUS_LOG_H
|
|
@ -1,279 +0,0 @@
|
|||
//
|
||||
// File: foldhaus_memory.h
|
||||
// Author: Peter Slattery
|
||||
// Creation Date: 2020-01-01
|
||||
//
|
||||
#ifndef FOLDHAUS_MEMORY_H
|
||||
|
||||
#ifndef GS_MEMORY_H
|
||||
|
||||
#if 0
|
||||
#ifndef GS_LANGUAGE_H
|
||||
|
||||
typedef uint8_t u8;
|
||||
typedef int8_t s8;
|
||||
typedef uint32_t u32;
|
||||
typedef int32_t s32;
|
||||
|
||||
internal void
|
||||
GSMemSet (u8* Base, s32 Value, s32 Count)
|
||||
{
|
||||
u8* Cursor = Base;
|
||||
for (s32 i = 0; i < Count; i++)
|
||||
{
|
||||
*Cursor++ = Value;
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
GSMemCopy (u8* Source, u8* Destination, s32 Count)
|
||||
{
|
||||
u8* Src = Source;
|
||||
u8* Dst = Destination;
|
||||
|
||||
for (s32 i = 0; i < Count; i++)
|
||||
{
|
||||
*Dst++ = *Src++;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // GS_LANGUAGE_H
|
||||
|
||||
#if !defined Assert && defined DEBUG
|
||||
#define Assert(expression) if(!(expression)){ *((int *)0) = 5; }
|
||||
#define InvalidCodePath Assert(0)
|
||||
#endif
|
||||
|
||||
#define MEMORY_REGION_PAGE_SIZE Megabytes(1)
|
||||
struct memory_region
|
||||
{
|
||||
u8* Base;
|
||||
u32 Size;
|
||||
u32 Used;
|
||||
memory_region* PreviousRegion;
|
||||
};
|
||||
|
||||
struct memory_arena
|
||||
{
|
||||
memory_region* CurrentRegion;
|
||||
platform_alloc* PlatformAlloc;
|
||||
};
|
||||
|
||||
internal memory_region*
|
||||
BootstrapRegionOntoMemory (u8* Memory, s32 Size)
|
||||
{
|
||||
Assert(Size > sizeof(memory_region));
|
||||
memory_region* Result = (memory_region*)Memory;
|
||||
Result->Base = Memory + sizeof(memory_region);
|
||||
Result->Size = Size - sizeof(memory_region);
|
||||
Result->Used = 0;
|
||||
Result->PreviousRegion = 0;
|
||||
return Result;
|
||||
}
|
||||
|
||||
#define PushStruct(arena, type) (type*)PushSize_(arena, sizeof(type))
|
||||
#define PushArray(arena, type, count) (type*)PushSize_(arena, sizeof(type)*count)
|
||||
#define PushSize(arena, size) PushSize_(arena, size)
|
||||
static u8*
|
||||
PushSize_ (memory_arena* Arena, u32 Size)
|
||||
{
|
||||
memory_region* PushOntoRegion = Arena->CurrentRegion;
|
||||
|
||||
if (!PushOntoRegion || PushOntoRegion->Used + Size > PushOntoRegion->Size)
|
||||
{
|
||||
// NOTE(Peter): we only search backwards if the item doesn't already fit in the most recent spot. This way, memory allocated
|
||||
// one after another is more likely to be contiguous. You can expect that two allocations performed back to back are also next
|
||||
// to eachother in memory most of the time.
|
||||
if (PushOntoRegion)
|
||||
{
|
||||
// NOTE(Peter): Search backwards through previous regions to see if there is a region allocated that has enough room
|
||||
// to fit this allocation
|
||||
memory_region* PreviousRegion = Arena->CurrentRegion->PreviousRegion;
|
||||
while (PreviousRegion)
|
||||
{
|
||||
if (PreviousRegion->Used + Size <= PreviousRegion->Size)
|
||||
{
|
||||
PushOntoRegion = PreviousRegion;
|
||||
break;
|
||||
}
|
||||
PreviousRegion = PreviousRegion->PreviousRegion;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PushOntoRegion || PushOntoRegion->Used + Size > PushOntoRegion->Size)
|
||||
{
|
||||
if (Arena->PlatformAlloc != 0)
|
||||
{
|
||||
// NOTE(Peter): Probably want to have this be a multiple of some minimum size so that we aren't constantly
|
||||
// allocating new pages.
|
||||
s32 SizeNeeded = Size + sizeof(memory_region);
|
||||
s32 RegionPagesNeeded = IntegerDivideRoundUp(SizeNeeded, MEMORY_REGION_PAGE_SIZE);
|
||||
s32 SizeToAllocate = RegionPagesNeeded * MEMORY_REGION_PAGE_SIZE;
|
||||
|
||||
u8* AllocResult = Arena->PlatformAlloc(SizeToAllocate);
|
||||
Assert(AllocResult);
|
||||
|
||||
memory_region* NewRegion = BootstrapRegionOntoMemory(AllocResult, SizeToAllocate);
|
||||
NewRegion->PreviousRegion = Arena->CurrentRegion;
|
||||
Arena->CurrentRegion = NewRegion;
|
||||
PushOntoRegion = Arena->CurrentRegion;
|
||||
}
|
||||
else
|
||||
{
|
||||
// NOTE(Peter): We ran out of memory in a memory arena that cannot/should not grow
|
||||
InvalidCodePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u8* Result = PushOntoRegion->Base + PushOntoRegion->Used;
|
||||
PushOntoRegion->Used += Size;
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
static void
|
||||
InitMemoryArena (memory_arena* Arena, u8* Base, u32 Size, platform_alloc* PlatformAlloc)
|
||||
{
|
||||
if (Base)
|
||||
{
|
||||
Arena->CurrentRegion = BootstrapRegionOntoMemory(Base, Size);
|
||||
}
|
||||
Arena->PlatformAlloc = PlatformAlloc;
|
||||
}
|
||||
|
||||
static memory_arena*
|
||||
BootstrapArenaIntoMemory (u8* Memory, u32 Size)
|
||||
{
|
||||
Assert(Size > sizeof(memory_arena));
|
||||
// NOTE(Peter): takes in a block of memory, places a memory arena at the head, and gives
|
||||
// the arena access to the rest of the block to use.
|
||||
memory_arena* Result = (memory_arena*)Memory;
|
||||
*Result = {};
|
||||
InitMemoryArena(Result, Memory + sizeof(memory_arena), Size - sizeof(memory_arena), 0);
|
||||
return Result;
|
||||
}
|
||||
|
||||
static memory_arena
|
||||
AllocateNonGrowableArenaWithSpace(platform_alloc* PlatformAlloc, s32 SizeNeeded)
|
||||
{
|
||||
// TODO(Peter): This causes a leak currently. If you don't free the whole region later, you'll end up with
|
||||
// the memory_region still being in memory. Should probably just make the first memory region be a member
|
||||
// variable, not a pointer, in the memory_arena struct.
|
||||
|
||||
memory_arena Result = {};
|
||||
|
||||
s32 AllocateSize = SizeNeeded + sizeof(memory_region);
|
||||
u8* Memory = PlatformAlloc(AllocateSize);
|
||||
Assert(Memory);
|
||||
|
||||
InitMemoryArena(&Result, Memory, AllocateSize, 0);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
static void
|
||||
ClearMemoryRegion (memory_region* Region)
|
||||
{
|
||||
#if 0
|
||||
// NOTE(Peter): Turn this on occasionally. This is a big time sink but it forces us into
|
||||
// correct memory usage since there's no error reporting for accessing memory the arena thinks
|
||||
// is unused. At least now, it'll be zero's.
|
||||
GSMemSet(Region->Base, 0, Region->Size);
|
||||
#endif
|
||||
Region->Used = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ClearArena (memory_arena* Arena)
|
||||
{
|
||||
memory_region* CurrentRegion = Arena->CurrentRegion;
|
||||
while (CurrentRegion)
|
||||
{
|
||||
ClearMemoryRegion(CurrentRegion);
|
||||
CurrentRegion = CurrentRegion->PreviousRegion;
|
||||
}
|
||||
}
|
||||
|
||||
struct arena_snapshot
|
||||
{
|
||||
memory_region* CurrentRegion;
|
||||
u32 UsedAtSnapshot;
|
||||
};
|
||||
|
||||
static arena_snapshot
|
||||
TakeSnapshotOfArena (memory_arena Arena)
|
||||
{
|
||||
arena_snapshot Result = {};
|
||||
Result.CurrentRegion = Arena.CurrentRegion;
|
||||
Result.UsedAtSnapshot = Arena.CurrentRegion->Used;
|
||||
return Result;
|
||||
};
|
||||
|
||||
static void
|
||||
ZeroArenaToSnapshot (memory_arena* Arena, arena_snapshot Snapshot)
|
||||
{
|
||||
memory_region* RegionCursor = Arena->CurrentRegion;
|
||||
while (RegionCursor && RegionCursor != Snapshot.CurrentRegion)
|
||||
{
|
||||
GSZeroMemory(RegionCursor->Base, RegionCursor->Size);
|
||||
RegionCursor = RegionCursor->PreviousRegion;
|
||||
}
|
||||
|
||||
Assert(RegionCursor == Snapshot.CurrentRegion);
|
||||
GSZeroMemory(RegionCursor->Base + Snapshot.UsedAtSnapshot,
|
||||
RegionCursor->Used - Snapshot.UsedAtSnapshot);
|
||||
}
|
||||
|
||||
static void
|
||||
ClearArenaToSnapshot (memory_arena* Arena, arena_snapshot Snapshot)
|
||||
{
|
||||
memory_region* RegionCursor = Arena->CurrentRegion;
|
||||
while (RegionCursor && RegionCursor != Snapshot.CurrentRegion)
|
||||
{
|
||||
RegionCursor->Used = 0;
|
||||
RegionCursor = RegionCursor->PreviousRegion;
|
||||
}
|
||||
|
||||
Assert(RegionCursor == Snapshot.CurrentRegion);
|
||||
RegionCursor->Used = Snapshot.UsedAtSnapshot;
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// Basic Memory Arena
|
||||
// A no-bookkeeping overhead version of the memory_arena above.
|
||||
//
|
||||
|
||||
struct static_memory_arena
|
||||
{
|
||||
u8* Base;
|
||||
u32 Size;
|
||||
u32 Used;
|
||||
};
|
||||
|
||||
static static_memory_arena
|
||||
CreateMemoryArena (u8* Base, u32 Size)
|
||||
{
|
||||
static_memory_arena Result = {};
|
||||
Result.Base = Base;
|
||||
Result.Size = Size;
|
||||
Result.Used = 0;
|
||||
return Result;
|
||||
}
|
||||
|
||||
#define PushArrayOnStaticArena(arena, type, length) (type*)PushSize_((arena), sizeof(type) * length)
|
||||
static u8*
|
||||
PushSize_ (static_memory_arena* Arena, u32 Size)
|
||||
{
|
||||
Assert(Arena->Used + Size <= Arena->Size);
|
||||
u8* Result = Arena->Base + Arena->Used;
|
||||
Arena->Used += Size;
|
||||
return Result;
|
||||
}
|
||||
|
||||
#define GS_MEMORY_H
|
||||
#endif // GS_MEMORY_H
|
||||
|
||||
#define FOLDHAUS_MEMORY_H
|
||||
#endif // FOLDHAUS_MEMORY_H
|
|
@ -151,6 +151,7 @@ PLATFORM_SET_SOCKET_OPTION(Win32SetSocketOption)
|
|||
if (Error == SOCKET_ERROR)
|
||||
{
|
||||
Error = WSAGetLastError();
|
||||
// TODO(Peter): :ErrorLogging
|
||||
}
|
||||
|
||||
return Error;
|
||||
|
@ -215,6 +216,7 @@ PLATFORM_SEND_TO(Win32SendTo)
|
|||
}
|
||||
else
|
||||
{
|
||||
// TODO(Peter): :ErrorLogging
|
||||
InvalidCodePath;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ LoadApplicationDLL(char* DLLName, win32_dll_refresh* DLLResult)
|
|||
b32 Success = false;
|
||||
Assert(DLLResult->DLL == 0);
|
||||
|
||||
DLLResult->DLL = LoadLibraryA(DLLName); // TODO(Peter): Error checking
|
||||
DLLResult->DLL = LoadLibraryA(DLLName);
|
||||
if (DLLResult->DLL)
|
||||
{
|
||||
Success = true;
|
||||
|
|
|
@ -31,7 +31,7 @@ PLATFORM_READ_ENTIRE_FILE(Win32ReadEntireFile)
|
|||
else
|
||||
{
|
||||
u32 Error = GetLastError();
|
||||
// TODO(Peter):
|
||||
// TODO(Peter): :ErrorLogging
|
||||
Result.Size = 0;
|
||||
Result.Error = PlatformMemory_UnknownError;
|
||||
}
|
||||
|
@ -41,6 +41,7 @@ PLATFORM_READ_ENTIRE_FILE(Win32ReadEntireFile)
|
|||
else
|
||||
{
|
||||
Result.Error = PlatformMemory_FileNotFound;
|
||||
// TODO(Peter): :ErrorLogging
|
||||
}
|
||||
|
||||
return Result;
|
||||
|
@ -100,7 +101,7 @@ GetFileLastWriteTime(char* Path)
|
|||
}
|
||||
else
|
||||
{
|
||||
// TODO(Peter): Error handling
|
||||
// TODO(Peter): :ErrorLogging
|
||||
}
|
||||
|
||||
return Result;
|
||||
|
|
3
todo.txt
3
todo.txt
|
@ -25,7 +25,8 @@ x File Loading
|
|||
x Gracefully handle File Not found
|
||||
|
||||
- Internal Log File
|
||||
- NOTE: This should not be a part of the debug system
|
||||
NOTE: This should not be a part of the debug system
|
||||
x Basic logging
|
||||
- Save output log to a file continuously
|
||||
- Have a window where we can view the log within the app
|
||||
- Create a bar that displays the most recent error message
|
||||
|
|
Loading…
Reference in New Issue