diff --git a/build_with_clang.bat b/build_with_clang.bat index bcda377..91e8c2e 100644 --- a/build_with_clang.bat +++ b/build_with_clang.bat @@ -1,11 +1,11 @@ @echo off echo ~~~ Metadesk Build ~~~ +set src=%cd% + rem TODO(mal): Review these warnings set accepted_clang_warnings=-Wno-deprecated-declarations -Wno-pointer-sign -Wno-writable-strings -Wno-unknown-warning-option -set compile_flags=-I../source/ %accepted_clang_warnings% - -set src=%cd% +set compile_flags=-I%src%/source/ %accepted_clang_warnings% if not exist build mkdir build pushd build diff --git a/samples/c_code_generation.c b/samples/c_code_generation.c index b57167a..ca0a170 100644 --- a/samples/c_code_generation.c +++ b/samples/c_code_generation.c @@ -7,9 +7,14 @@ #include "md.c" #include "md_c_helpers.c" +static MD_Arena *arena = 0; + int main(int argument_count, char **arguments) { - MD_Arena *arena = MD_ArenaNew(1ull << 40); + MD_ThreadContext tctx; + MD_ThreadInit(&tctx); + + arena = MD_ArenaNew(1ull << 40); MD_String8 example_code = MD_S8Lit("@struct Foo:\n" "{\n" diff --git a/samples/node_errors/node_errors.c b/samples/node_errors/node_errors.c index f83a732..7850007 100644 --- a/samples/node_errors/node_errors.c +++ b/samples/node_errors/node_errors.c @@ -3,9 +3,14 @@ #include "md.h" #include "md.c" +static MD_Arena *arena = 0; + int main(int argument_count, char **arguments) { - MD_Arena *arena = MD_ArenaNew(1ull << 40); + MD_ThreadContext tctx; + MD_ThreadInit(&tctx); + + arena = MD_ArenaNew(1ull << 40); // NOTE(rjf): Parse all the files passed in via command line. MD_Node *list = MD_MakeList(arena); diff --git a/samples/old_style_custom_layer.c b/samples/old_style_custom_layer.c index 6dd91d8..c5cc2a9 100644 --- a/samples/old_style_custom_layer.c +++ b/samples/old_style_custom_layer.c @@ -3,6 +3,8 @@ #include "md.h" #include "md.c" +static MD_Arena *arena = 0; + static void Initialize(void) { @@ -23,7 +25,10 @@ CleanUp(void) int main(int argument_count, char **arguments) { - MD_Arena *arena = MD_ArenaNew(1ull << 40); + MD_ThreadContext tctx; + MD_ThreadInit(&tctx); + + arena = MD_ArenaNew(1ull << 40); // NOTE(rjf): Parse all the files passed in via command line. MD_Node *list = MD_MakeList(arena); diff --git a/samples/output_parse/output_parse.c b/samples/output_parse/output_parse.c index cfc2b03..5f3771d 100644 --- a/samples/output_parse/output_parse.c +++ b/samples/output_parse/output_parse.c @@ -64,6 +64,9 @@ static void PrintNode(MD_Node* node, FILE* file, int indent_count) { int main(int argument_count, char **arguments) { + MD_ThreadContext tctx; + MD_ThreadInit(&tctx); + arena = MD_ArenaNew(1ull << 40); // NOTE(pmh): Parse all the files passed in via command line. diff --git a/samples/parse_check.c b/samples/parse_check.c index b68de9f..25e92dd 100644 --- a/samples/parse_check.c +++ b/samples/parse_check.c @@ -1,9 +1,14 @@ #include "md.h" #include "md.c" +static MD_Arena *arena = 0; + int main(int argument_count, char **arguments) { - MD_Arena *arena = MD_ArenaNew(1ull << 40); + MD_ThreadContext tctx; + MD_ThreadInit(&tctx); + + arena = MD_ArenaNew(1ull << 40); MD_Node *list = MD_MakeList(arena); for(int i = 1; i < argument_count; i += 1) diff --git a/samples/static_site_generator/example_site/generated/site.js b/samples/static_site_generator/example_site/generated/site.js index d38215e..e69de29 100644 --- a/samples/static_site_generator/example_site/generated/site.js +++ b/samples/static_site_generator/example_site/generated/site.js @@ -1,61 +0,0 @@ -function StringFitsFilter(str, filter) -{ - let match = true; - let filter_upper = filter.toUpperCase(); - let filter_substrings = filter_upper.split(/[ _*]+/); - let str_upper = str.toUpperCase(); - let minimum_index = 0; - - for(let i = 0; i < filter_substrings.length; ++i) - { - if(filter_substrings[i].length > 0) - { - let index_of_substring = str_upper.indexOf(filter_substrings[i], minimum_index); - if(index_of_substring < 0 || index_of_substring < minimum_index) - { - match = false; - break; - } - minimum_index = index_of_substring + filter_substrings[i].length - 1; - } - } - - return match; -} - -function UpdateListByFilter(menu_id, filter_id) -{ - let ul = document.getElementById(menu_id); - let li = ul.getElementsByTagName("li"); - let input = document.getElementById(filter_id); - let filter = input.value.toUpperCase(); - for(let i = 0; i < li.length; i++) - { - if(filter.length > 0) - { - let a = li[i].getElementsByTagName("a")[0]; - if(StringFitsFilter(a.innerHTML, filter)) - { - li[i].style.display = ""; - } - else - { - li[i].style.display = "none"; - } - } - else - { - li[i].style.display = ""; - } - } -} - -function SearchInput(event, lister_idx) -{ - UpdateListByFilter("lister_"+lister_idx, "lister_search_"+lister_idx); -} - -function SearchKeyDown(event, lister_idx) -{ - UpdateListByFilter("lister_"+lister_idx, "lister_search_"+lister_idx); -} \ No newline at end of file diff --git a/samples/static_site_generator/static_site_generator.c b/samples/static_site_generator/static_site_generator.c index d136fba..fd1f210 100644 --- a/samples/static_site_generator/static_site_generator.c +++ b/samples/static_site_generator/static_site_generator.c @@ -34,6 +34,9 @@ static MD_Arena *arena = 0; int main(int argument_count, char **arguments) { + MD_ThreadContext tctx; + MD_ThreadInit(&tctx); + arena = MD_ArenaNew(1ull << 40); //~ NOTE(rjf): Parse command line arguments. diff --git a/samples/toy_language/toy_language.c b/samples/toy_language/toy_language.c index 6c352ab..785468b 100644 --- a/samples/toy_language/toy_language.c +++ b/samples/toy_language/toy_language.c @@ -182,6 +182,9 @@ EvaluateScope(NamespaceNode *ns, MD_Node *code) int main(int argument_count, char **arguments) { + MD_ThreadContext tctx; + MD_ThreadInit(&tctx); + arena = MD_ArenaNew(1ull << 40); //- rjf: parse command line diff --git a/source/md.c b/source/md.c index 872a93a..0454962 100644 --- a/source/md.c +++ b/source/md.c @@ -9,15 +9,16 @@ // #define MD_IMPL_Release // #define MD_IMPL_ArenaNew // #define MD_IMPL_ArenaRelease +// #define MD_SCRATCH_SIZE // Default Implementation Controls // #define MD_NO_DEFAULT_IMPL -> skip code for all default implementations #if !defined(MD_NO_DEFAULT_IMPL) # define MD_NO_DEFAULT_IMPL 0 #endif - -// TODO(allen): not real! Don't put into API -MD_FUNCTION MD_Arena* MD_Scratch(void); +#if !defined(MD_SCRATCH_SIZE) +# define MD_SCRATCH_SIZE (1 << 30) +#endif //~///////////////////////////////////////////////////////////////////////////// ////////////////////////// Win32 Implementation //////////////////////////////// @@ -38,6 +39,8 @@ MD_WIN32_FileIterIncrement(MD_Arena *arena, MD_FileIter *it, MD_String8 path, { MD_b32 result = 0; + MD_ArenaTemp scratch = MD_GetScratch(&arena, 1); + WIN32_FIND_DATAA find_data = MD_ZERO_STRUCT; HANDLE state = *(HANDLE *)(&it->state[0]); if(state == 0) @@ -48,7 +51,7 @@ MD_WIN32_FileIterIncrement(MD_Arena *arena, MD_FileIter *it, MD_String8 path, { need_star = 1; } - MD_String8 cpath = need_star ? MD_S8Fmt(MD_Scratch(), "%.*s*", MD_S8VArg(path)) : path; + MD_String8 cpath = need_star ? MD_S8Fmt(scratch.arena, "%.*s*", MD_S8VArg(path)) : path; state = FindFirstFileA((char*)cpath.str, &find_data); result = !!state; } @@ -70,6 +73,8 @@ MD_WIN32_FileIterIncrement(MD_Arena *arena, MD_FileIter *it, MD_String8 path, ((MD_u64)find_data.nFileSizeLow)); } + MD_ReleaseScratch(scratch); + return result; } @@ -400,24 +405,39 @@ MD_ArenaRelease(MD_Arena *arena){ MD_IMPL_ArenaRelease(arena); } +//~ Thread Context Functions -// TODO(allen): // TODO(allen): // TODO(allen): // TODO(allen): FIX FIX FIX FIX -// TODO(allen): // TODO(allen): // TODO(allen): // TODO(allen): FIX FIX FIX FIX -// TODO(allen): // TODO(allen): // TODO(allen): // TODO(allen): FIX FIX FIX FIX -// TODO(allen): // TODO(allen): // TODO(allen): // TODO(allen): FIX FIX FIX FIX -// This is a hack to ease the transition complexity, it defines "scratch" as -// a single global arena that can be acquired anywhere without explicit pass -// through -- but it is not a real scratch system because it has no free mechanism! +MD_THREAD_LOCAL MD_ThreadContext *md_thread_ctx; -MD_FUNCTION_IMPL MD_Arena* -MD_Scratch(void){ - static MD_Arena *scratch = 0; - if (scratch == 0){ - scratch = MD_ArenaNew(1ull << 40); +MD_FUNCTION_IMPL void +MD_ThreadInit(MD_ThreadContext *tctx_mem){ + md_thread_ctx = tctx_mem; + for (MD_u32 i = 0; i < MD_ArrayCount(md_thread_ctx->scratch_pool); i += 1){ + tctx_mem->scratch_pool[i] = MD_ArenaNew(MD_SCRATCH_SIZE); } - return(scratch); } +MD_FUNCTION_IMPL MD_ArenaTemp +MD_GetScratch(MD_Arena **conflicts, MD_u32 count){ + MD_ArenaTemp result = MD_ZERO_STRUCT; + MD_ThreadContext *tctx = md_thread_ctx; + MD_Arena **arena_ptr = tctx->scratch_pool; + for (MD_u32 i = 0; i < MD_ArrayCount(tctx->scratch_pool); i += 1, arena_ptr += 1){ + MD_b32 has_conflict = 0; + MD_Arena **conflict_ptr = conflicts; + for (MD_u32 j = 0; j < count; j += 1, conflict_ptr += 1){ + if (*arena_ptr == *conflict_ptr){ + has_conflict = 1; + break; + } + } + if (!has_conflict){ + result = MD_ArenaBeginTemp(*arena_ptr); + break; + } + } + return(result); +} //~ Characters @@ -2659,8 +2679,10 @@ MD_PrintMessageFmt(FILE *out, MD_CodeLoc loc, MD_MessageKind kind, char *fmt, .. { va_list args; va_start(args, fmt); - MD_String8 string = MD_S8FmtV(MD_Scratch(), fmt, args); + MD_ArenaTemp scratch = MD_GetScratch(0, 0); + MD_String8 string = MD_S8FmtV(scratch.arena, fmt, args); MD_PrintMessage(out, loc, kind, string); + MD_ReleaseScratch(scratch); va_end(args); } @@ -2676,8 +2698,10 @@ MD_PrintNodeMessageFmt(FILE *out, MD_Node *node, MD_MessageKind kind, char *fmt, { va_list args; va_start(args, fmt); - MD_String8 string = MD_S8FmtV(MD_Scratch(), fmt, args); + MD_ArenaTemp scratch = MD_GetScratch(0, 0); + MD_String8 string = MD_S8FmtV(scratch.arena, fmt, args); MD_PrintNodeMessage(out, node, kind, string); + MD_ReleaseScratch(scratch); va_end(args); } @@ -2961,8 +2985,10 @@ MD_FUNCTION MD_i64 MD_CmdLineI64FromString(MD_CmdLine cmdln, MD_String8 name) { MD_String8List values = MD_CmdLineValuesFromString(cmdln, name); - MD_String8 value_str = MD_S8ListJoin(MD_Scratch(), values, 0); + MD_ArenaTemp scratch = MD_GetScratch(0, 0); + MD_String8 value_str = MD_S8ListJoin(scratch.arena, values, 0); MD_i64 result = MD_CStyleIntFromString(value_str); + MD_ReleaseScratch(scratch); return(result); } diff --git a/source/md.h b/source/md.h index 3e1336b..e1158fa 100644 --- a/source/md.h +++ b/source/md.h @@ -224,6 +224,12 @@ # define MD_C_LINKAGE_END } #endif +#if MD_COMPILER_CL +# define MD_THREAD_LOCAL __declspec(thread) +#elif MD_COMPILER_GCC || MD_COMPILER_CLANG +# define MD_THREAD_LOCAL __thread +#endif + //~ Common defines #define MD_FUNCTION @@ -260,6 +266,8 @@ union MD_IntPtr{ void *ptr; }; +typedef struct MD_Arena MD_Arena; + typedef enum MD_ArenaOperation{ MD_ArenaOperation_GetPos, MD_ArenaOperation_GetCap, @@ -269,9 +277,8 @@ typedef enum MD_ArenaOperation{ MD_ArenaOperation_SetAutoAlign, } MD_ArenaOperation; -typedef MD_IntPtr MD_ArenaFunc(struct MD_Arena *arena, MD_ArenaOperation op, MD_u64 v); +typedef MD_IntPtr MD_ArenaFunc(MD_Arena *arena, MD_ArenaOperation op, MD_u64 v); -typedef struct MD_Arena MD_Arena; struct MD_Arena{ MD_ArenaFunc *func; }; @@ -284,6 +291,13 @@ struct MD_ArenaTemp{ MD_u64 pos; }; +//~ Thread Context + +typedef struct MD_ThreadContext MD_ThreadContext; +struct MD_ThreadContext{ + MD_Arena *scratch_pool[2]; +}; + //~ Basic Unicode string types. typedef struct MD_String8 MD_String8; @@ -703,6 +717,13 @@ sizeof(T)*(c))) MD_FUNCTION MD_Arena* MD_ArenaNew(MD_u64 cap); MD_FUNCTION void MD_ArenaRelease(MD_Arena *arena); +//~ Thread Context Functions + +MD_FUNCTION void MD_ThreadInit(MD_ThreadContext *tctx_mem); +MD_FUNCTION MD_ArenaTemp MD_GetScratch(MD_Arena **conflicts, MD_u32 count); + +#define MD_ReleaseScratch(scratch) MD_ArenaEndTemp(scratch) + //~ Characters MD_FUNCTION MD_b32 MD_CharIsAlpha(MD_u8 c); diff --git a/source/md_c_helpers.c b/source/md_c_helpers.c index c61d43b..e88087c 100644 --- a/source/md_c_helpers.c +++ b/source/md_c_helpers.c @@ -704,8 +704,10 @@ MD_C_Generate_Decl(FILE *file, MD_Node *node) { if(node) { - MD_C_Expr *type = MD_C_ParseAsType(MD_Scratch(), node->first_child, node->last_child); + MD_ArenaTemp scratch = MD_GetScratch(0, 0); + MD_C_Expr *type = MD_C_ParseAsType(scratch.arena, node->first_child, node->last_child); MD_C_Generate_DeclByNameAndType(file, node->string, type); + MD_ReleaseScratch(scratch); } } diff --git a/tests/cpp_build_test.cpp b/tests/cpp_build_test.cpp index 9c30e95..33b4634 100644 --- a/tests/cpp_build_test.cpp +++ b/tests/cpp_build_test.cpp @@ -1,9 +1,14 @@ #include "md.h" #include "md.c" +static MD_Arena *arena = 0; + int main(void) { - MD_Arena *arena = MD_ArenaNew(1ull << 40); + MD_ThreadContext tctx; + MD_ThreadInit(&tctx); + + arena = MD_ArenaNew(1ull << 40); printf("%d\n", MD_CPP_VERSION); diff --git a/tests/sanity_tests.c b/tests/sanity_tests.c index fe1c9cd..495c680 100644 --- a/tests/sanity_tests.c +++ b/tests/sanity_tests.c @@ -120,6 +120,9 @@ TokenMatch(MD_Token token, MD_String8 string, MD_TokenKind kind) int main(void) { + MD_ThreadContext tctx; + MD_ThreadInit(&tctx); + arena = MD_ArenaNew(1ull << 40); Test("Lexer") diff --git a/tests/unicode_test.c b/tests/unicode_test.c index 36fb310..d40220f 100644 --- a/tests/unicode_test.c +++ b/tests/unicode_test.c @@ -16,6 +16,9 @@ void run_test_on_string(MD_String8 string) int main(void) { + MD_ThreadContext tctx; + MD_ThreadInit(&tctx); + arena = MD_ArenaNew(1ull << 40); // TODO(allen): throw more at this.