diff --git a/src/check_type.cpp b/src/check_type.cpp index a23033ef1..9921ae6ae 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -39,11 +39,6 @@ gb_internal void populate_using_entity_scope(CheckerContext *ctx, Ast *node, Ast } Type *original_type = t; t = base_type(type_deref(t)); - gbString str = nullptr; - defer (gb_string_free(str)); - if (node != nullptr) { - str = expr_to_string(node); - } if (t->kind == Type_Struct) { for (Entity *f : t->Struct.fields) { @@ -54,8 +49,10 @@ gb_internal void populate_using_entity_scope(CheckerContext *ctx, Ast *node, Ast if (e != nullptr && name != "_") { gbString ot = type_to_string(original_type); // TODO(bill): Better type error - if (str != nullptr) { + if (node != nullptr) { + gbString str = expr_to_string(node); error(e->token, "'%.*s' is already declared in '%s', through 'using' from '%s'", LIT(name), str, ot); + gb_string_free(str); } else { error(e->token, "'%.*s' is already declared, through 'using' from '%s'", LIT(name), ot); } diff --git a/src/checker.cpp b/src/checker.cpp index 0897fdbce..ba6a392dd 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -3282,48 +3282,24 @@ gb_internal Type *find_type_in_pkg(CheckerInfo *info, String const &pkg, String return e->type; } -struct CheckerTypePathStore { - CheckerTypePath path; - std::atomic next; -}; - -gb_internal gb_thread_local std::atomic checker_type_path_free_list; +gb_internal gb_thread_local std::atomic *> checker_type_path_free_list; gb_internal CheckerTypePath *new_checker_type_path(gbAllocator allocator) { // TODO(bill): Cache to reuse `CheckerTypePath - CheckerTypePathStore *tp = nullptr; - - for (;;) { - tp = checker_type_path_free_list.load(std::memory_order_acquire); - if (tp == nullptr) { - tp = permanent_alloc_item(); - array_init(&tp->path, allocator, 0, 16); - return &tp->path; - } - - if (checker_type_path_free_list.compare_exchange_weak(tp, tp->next.load(std::memory_order_acquire), std::memory_order_acquire, std::memory_order_relaxed)) { - tp->next.store(nullptr); - return &tp->path; - } - + auto *tp = atomic_freelist_get(checker_type_path_free_list); + if (tp == nullptr) { + tp = permanent_alloc_item >(); + array_init(&tp->value, allocator, 0, 16); } + return &tp->value; } gb_internal void destroy_checker_type_path(CheckerTypePath *path, gbAllocator allocator) { - auto *tp = cast(CheckerTypePathStore *)path; - array_clear(&tp->path); + auto *tp = cast(AtomicFreelist *)path; + array_clear(&tp->value); - - for (;;) { - auto *head = checker_type_path_free_list.load(std::memory_order_relaxed); - tp->next.store(head); - if (checker_type_path_free_list.compare_exchange_weak(head, tp, std::memory_order_release, std::memory_order_relaxed)) { - return; - } - } - - // array_free(&tp->path); + atomic_freelist_put(checker_type_path_free_list, tp); } gb_internal void check_type_path_push(CheckerContext *c, Entity *e) { diff --git a/src/threading.cpp b/src/threading.cpp index d8ae321f5..5dff13d2e 100644 --- a/src/threading.cpp +++ b/src/threading.cpp @@ -1201,3 +1201,41 @@ void futex_wait(Futex *f, Footex val) { #if defined(GB_SYSTEM_WINDOWS) #pragma warning(pop) #endif + + + +template +struct AtomicFreelist { + T value; + std::atomic *> next; +}; + +template +AtomicFreelist *atomic_freelist_get(std::atomic *> &head) { + AtomicFreelist *elem = nullptr; + + for (;;) { + elem = head.load(std::memory_order_acquire); + if (elem == nullptr) { + return nullptr; + } + + if (head.compare_exchange_weak(elem, elem->next.load(std::memory_order_acquire), std::memory_order_acquire, std::memory_order_relaxed)) { + elem->next.store(nullptr, std::memory_order_relaxed); + return elem; + } + + } +} + +template +void atomic_freelist_put(std::atomic *> &head_list, AtomicFreelist *elem) { + for (;;) { + auto *head = head_list.load(std::memory_order_relaxed); + elem->next.store(head, std::memory_order_relaxed); + if (head_list.compare_exchange_weak(head, elem, std::memory_order_release, std::memory_order_relaxed)) { + return; + } + + } +} \ No newline at end of file