aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2021-07-14 23:49:35 +0100
committergingerBill <bill@gingerbill.org>2021-07-14 23:49:35 +0100
commit981b9fb7a818ba607ac05f9efdc84fc8daa78344 (patch)
treedfc6e04010419680e9b7750d60e7b821f6056630 /src
parent10f4d8df32f73e3c5071a6e168a0923a53d8332f (diff)
Remove need for scope mutex, make Scope singly linked list tree with atomic pointers
Diffstat (limited to 'src')
-rw-r--r--src/checker.cpp19
-rw-r--r--src/checker.hpp8
2 files changed, 9 insertions, 18 deletions
diff --git a/src/checker.cpp b/src/checker.cpp
index 3800f3e4c..0332d04b8 100644
--- a/src/checker.cpp
+++ b/src/checker.cpp
@@ -32,8 +32,7 @@ bool is_operand_undef(Operand o) {
void scope_reset(Scope *scope) {
if (scope == nullptr) return;
- scope->first_child = nullptr;
- scope->last_child = nullptr;
+ scope->head_child.store(nullptr, std::memory_order_relaxed);
string_map_clear(&scope->elements);
ptr_set_clear(&scope->imported);
}
@@ -233,10 +232,10 @@ Scope *create_scope(CheckerInfo *info, Scope *parent, isize init_elements_capaci
s->delayed_directives.allocator = heap_allocator();
if (parent != nullptr && parent != builtin_pkg->scope) {
- // TODO(bill): make this an atomic operation
- if (info) mutex_lock(&info->scope_mutex);
- DLIST_APPEND(parent->first_child, parent->last_child, s);
- if (info) mutex_unlock(&info->scope_mutex);
+ Scope *prev_head_child = parent->head_child.exchange(s, std::memory_order_acq_rel);
+ if (prev_head_child) {
+ prev_head_child->next.store(s, std::memory_order_release);
+ }
}
if (parent != nullptr && parent->flags & ScopeFlag_ContextDefined) {
@@ -305,7 +304,7 @@ void destroy_scope(Scope *scope) {
}
}
- for (Scope *child = scope->first_child; child != nullptr; child = child->next) {
+ for (Scope *child = scope->head_child; child != nullptr; child = child->next) {
destroy_scope(child);
}
@@ -625,9 +624,7 @@ void check_scope_usage(Checker *c, Scope *scope) {
array_free(&vetted_entities);
- for (Scope *child = scope->first_child;
- child != nullptr;
- child = child->next) {
+ for (Scope *child = scope->head_child; child != nullptr; child = child->next) {
if (child->flags & (ScopeFlag_Proc|ScopeFlag_Type|ScopeFlag_File)) {
// Ignore these
} else {
@@ -875,7 +872,6 @@ void init_checker_info(CheckerInfo *i) {
mutex_init(&i->deps_mutex);
mutex_init(&i->identifier_uses_mutex);
mutex_init(&i->foreign_mutex);
- mutex_init(&i->scope_mutex);
#undef TIME_SECTION
}
@@ -906,7 +902,6 @@ void destroy_checker_info(CheckerInfo *i) {
mutex_destroy(&i->deps_mutex);
mutex_destroy(&i->identifier_uses_mutex);
mutex_destroy(&i->foreign_mutex);
- mutex_destroy(&i->scope_mutex);
}
CheckerContext make_checker_context(Checker *c) {
diff --git a/src/checker.hpp b/src/checker.hpp
index 2a5ab0f44..f11df39e6 100644
--- a/src/checker.hpp
+++ b/src/checker.hpp
@@ -187,11 +187,8 @@ enum { DEFAULT_SCOPE_CAPACITY = 29 };
struct Scope {
Ast * node;
Scope * parent;
- // TODO(bill): make this is an ATOMIC singular linked list
- Scope * prev;
- Scope * next;
- Scope * first_child;
- Scope * last_child;
+ std::atomic<Scope *> next;
+ std::atomic<Scope *> head_child;
StringMap<Entity *> elements;
Array<Ast *> delayed_directives;
@@ -299,7 +296,6 @@ struct CheckerInfo {
// these variables will be of contention
BlockingMutex deps_mutex; // NOT recursive & Only used in `check_proc_body`
- BlockingMutex scope_mutex; // NOT recursive & Only used in `create_scope`
gbMutex gen_procs_mutex; // Possibly recursive
gbMutex gen_types_mutex; // Possibly recursive