diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index a7d5536e7..290b1b8cd 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -1687,7 +1687,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As case BuiltinProc___entry_point: operand->mode = Addressing_NoValue; operand->type = nullptr; - mpmc_enqueue(&c->info->intrinsics_entry_point_usage, call); + mpsc_enqueue(&c->info->intrinsics_entry_point_usage, call); break; case BuiltinProc_DIRECTIVE: diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 8f4534fb9..a21461454 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -1124,7 +1124,7 @@ gb_internal void check_global_variable_decl(CheckerContext *ctx, Entity *&e, Ast if (ac.require_declaration) { e->flags |= EntityFlag_Require; - mpmc_enqueue(&ctx->info->required_global_variable_queue, e); + mpsc_enqueue(&ctx->info->required_global_variable_queue, e); } diff --git a/src/checker.cpp b/src/checker.cpp index 5ffdfab55..354e033aa 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1160,11 +1160,11 @@ gb_internal void init_checker_info(CheckerInfo *i) { TIME_SECTION("checker info: mpmc queues"); - mpmc_init(&i->entity_queue, a, 1<<20); - mpsc_init(&i->definition_queue, a); //, 1<<20); - mpmc_init(&i->required_global_variable_queue, a, 1<<10); - mpmc_init(&i->required_foreign_imports_through_force_queue, a, 1<<10); - mpmc_init(&i->intrinsics_entry_point_usage, a, 1<<10); // just waste some memory here, even if it probably never used + mpsc_init(&i->entity_queue, a); // 1<<20); + mpsc_init(&i->definition_queue, a); //); // 1<<20); + mpsc_init(&i->required_global_variable_queue, a); // 1<<10); + mpsc_init(&i->required_foreign_imports_through_force_queue, a); // 1<<10); + mpsc_init(&i->intrinsics_entry_point_usage, a); // 1<<10); // just waste some memory here, even if it probably never used } gb_internal void destroy_checker_info(CheckerInfo *i) { @@ -1181,10 +1181,10 @@ gb_internal void destroy_checker_info(CheckerInfo *i) { array_free(&i->variable_init_order); array_free(&i->required_foreign_imports_through_force); - mpmc_destroy(&i->entity_queue); + mpsc_destroy(&i->entity_queue); mpsc_destroy(&i->definition_queue); - mpmc_destroy(&i->required_global_variable_queue); - mpmc_destroy(&i->required_foreign_imports_through_force_queue); + mpsc_destroy(&i->required_global_variable_queue); + mpsc_destroy(&i->required_foreign_imports_through_force_queue); map_destroy(&i->objc_msgSend_types); string_map_destroy(&i->load_file_cache); @@ -1711,7 +1711,8 @@ gb_internal void add_entity_and_decl_info(CheckerContext *c, Ast *identifier, En is_lazy = (e->flags & EntityFlag_Lazy) == EntityFlag_Lazy; if (!is_lazy) { - queue_count = mpmc_enqueue(&info->entity_queue, e); + GB_ASSERT(e != nullptr); + queue_count = mpsc_enqueue(&info->entity_queue, e); } if (e->token.pos.file_id != 0) { @@ -2375,12 +2376,12 @@ gb_internal void generate_minimum_dependency_set(Checker *c, Entity *start) { } } - for (Entity *e; mpmc_dequeue(&c->info.required_foreign_imports_through_force_queue, &e); /**/) { + for (Entity *e; mpsc_dequeue(&c->info.required_foreign_imports_through_force_queue, &e); /**/) { array_add(&c->info.required_foreign_imports_through_force, e); add_dependency_to_set(c, e); } - for (Entity *e; mpmc_dequeue(&c->info.required_global_variable_queue, &e); /**/) { + for (Entity *e; mpsc_dequeue(&c->info.required_global_variable_queue, &e); /**/) { e->flags |= EntityFlag_Used; add_dependency_to_set(c, e); } @@ -4058,6 +4059,7 @@ gb_internal void check_all_global_entities(Checker *c) { // Don't bother trying for_array(i, c->info.entities) { Entity *e = c->info.entities[i]; + GB_ASSERT(e != nullptr); if (e->flags & EntityFlag_Lazy) { continue; } @@ -4461,7 +4463,7 @@ gb_internal void check_add_foreign_import_decl(CheckerContext *ctx, Ast *decl) { AttributeContext ac = {}; check_decl_attributes(ctx, fl->attributes, foreign_import_decl_attribute, &ac); if (ac.require_declaration) { - mpmc_enqueue(&ctx->info->required_foreign_imports_through_force_queue, e); + mpsc_enqueue(&ctx->info->required_foreign_imports_through_force_queue, e); add_entity_use(ctx, nullptr, e); } if (ac.foreign_import_priority_index != 0) { @@ -5575,7 +5577,7 @@ gb_internal void check_unique_package_names(Checker *c) { gb_internal void check_add_entities_from_queues(Checker *c) { isize cap = c->info.entities.count + c->info.entity_queue.count.load(std::memory_order_relaxed); array_reserve(&c->info.entities, cap); - for (Entity *e; mpmc_dequeue(&c->info.entity_queue, &e); /**/) { + for (Entity *e; mpsc_dequeue(&c->info.entity_queue, &e); /**/) { array_add(&c->info.entities, e); } } @@ -5843,7 +5845,7 @@ gb_internal void check_parsed_files(Checker *c) { if (c->info.intrinsics_entry_point_usage.count > 0) { TIME_SECTION("check intrinsics.__entry_point usage"); Ast *node = nullptr; - while (mpmc_dequeue(&c->info.intrinsics_entry_point_usage, &node)) { + while (mpsc_dequeue(&c->info.intrinsics_entry_point_usage, &node)) { if (c->info.entry_point == nullptr && node != nullptr) { if (node->file()->pkg->kind != Package_Runtime) { warning(node, "usage of intrinsics.__entry_point will be a no-op"); diff --git a/src/checker.hpp b/src/checker.hpp index 356dd1fc8..7c545a716 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -380,11 +380,11 @@ struct CheckerInfo { // NOTE(bill): These are actually MPSC queues // TODO(bill): Convert them to be MPSC queues MPSCQueue definition_queue; - MPMCQueue entity_queue; - MPMCQueue required_global_variable_queue; - MPMCQueue required_foreign_imports_through_force_queue; + MPSCQueue entity_queue; + MPSCQueue required_global_variable_queue; + MPSCQueue required_foreign_imports_through_force_queue; - MPMCQueue intrinsics_entry_point_usage; + MPSCQueue intrinsics_entry_point_usage; BlockingMutex objc_types_mutex; PtrMap objc_msgSend_types; diff --git a/src/common.cpp b/src/common.cpp index 6a6019482..68d99ef02 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -43,11 +43,21 @@ gb_internal void debugf(char const *fmt, ...); #error Odin on Windows requires a 64-bit build-system. The 'Developer Command Prompt' for VS still defaults to 32-bit shell. The 64-bit shell can be found under the name 'x64 Native Tools Command Prompt' for VS. For more information, please see https://odin-lang.org/docs/install/#for-windows #endif +template +struct TypeIsPointer { + enum {value = false}; +}; + +template +struct TypeIsPointer { + enum {value = true}; +}; + #include "unicode.cpp" #include "array.cpp" #include "threading.cpp" -#include "queue.cpp" #include "common_memory.cpp" +#include "queue.cpp" #include "string.cpp" #include "range_cache.cpp" diff --git a/src/ptr_set.cpp b/src/ptr_set.cpp index 019ede8a5..2b8f38fef 100644 --- a/src/ptr_set.cpp +++ b/src/ptr_set.cpp @@ -1,14 +1,3 @@ -template -struct TypeIsPointer { - enum {value = false}; -}; - -template -struct TypeIsPointer { - enum {value = true}; -}; - - template struct PtrSet { static_assert(TypeIsPointer::value, "PtrSet::T must be a pointer"); diff --git a/src/queue.cpp b/src/queue.cpp index 845f87310..d3fd69c52 100644 --- a/src/queue.cpp +++ b/src/queue.cpp @@ -69,10 +69,13 @@ gb_internal bool mpsc_dequeue(MPSCQueue *q, T *value_) { if (next) { q->tail.store(next, std::memory_order_relaxed); // `tail` is now "dead" and needs to be "freed" - if (*value_) *value_ = next->value; + tail->value = next->value; + T value = tail->value; + if (value_) *value_ = value; q->count.fetch_sub(1, std::memory_order_acq_rel); return true; } + GB_ASSERT(q->count.load(std::memory_order_acquire) == 0); return false; }