mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-04 22:58:46 +00:00
Use RwMutex for the Scope
This commit is contained in:
+8
-4
@@ -381,8 +381,8 @@ gb_internal void override_entity_in_scope(Entity *original_entity, Entity *new_e
|
|||||||
if (found_scope == nullptr) {
|
if (found_scope == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mutex_lock(&found_scope->mutex);
|
rw_mutex_lock(&found_scope->mutex);
|
||||||
defer (mutex_unlock(&found_scope->mutex));
|
defer (rw_mutex_unlock(&found_scope->mutex));
|
||||||
|
|
||||||
// IMPORTANT NOTE(bill, 2021-04-10): Overriding behaviour was flawed in that the
|
// IMPORTANT NOTE(bill, 2021-04-10): Overriding behaviour was flawed in that the
|
||||||
// original entity was still used check checked, but the checking was only
|
// original entity was still used check checked, but the checking was only
|
||||||
@@ -1478,7 +1478,8 @@ gb_internal bool check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *de
|
|||||||
if (t->kind == Type_Struct) {
|
if (t->kind == Type_Struct) {
|
||||||
Scope *scope = t->Struct.scope;
|
Scope *scope = t->Struct.scope;
|
||||||
GB_ASSERT(scope != nullptr);
|
GB_ASSERT(scope != nullptr);
|
||||||
MUTEX_GUARD_BLOCK(scope->mutex) for (auto const &entry : scope->elements) {
|
rw_mutex_lock(&scope->mutex);
|
||||||
|
for (auto const &entry : scope->elements) {
|
||||||
Entity *f = entry.value;
|
Entity *f = entry.value;
|
||||||
if (f->kind == Entity_Variable) {
|
if (f->kind == Entity_Variable) {
|
||||||
Entity *uvar = alloc_entity_using_variable(e, f->token, f->type, nullptr);
|
Entity *uvar = alloc_entity_using_variable(e, f->token, f->type, nullptr);
|
||||||
@@ -1488,6 +1489,7 @@ gb_internal bool check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *de
|
|||||||
array_add(&using_entities, puv);
|
array_add(&using_entities, puv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
rw_mutex_unlock(&scope->mutex);
|
||||||
} else {
|
} else {
|
||||||
error(e->token, "'using' can only be applied to variables of type struct");
|
error(e->token, "'using' can only be applied to variables of type struct");
|
||||||
break;
|
break;
|
||||||
@@ -1496,7 +1498,8 @@ gb_internal bool check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *de
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MUTEX_GUARD_BLOCK(ctx->scope->mutex) for (auto const &entry : using_entities) {
|
rw_mutex_lock(&ctx->scope->mutex);
|
||||||
|
for (auto const &entry : using_entities) {
|
||||||
Entity *e = entry.e;
|
Entity *e = entry.e;
|
||||||
Entity *uvar = entry.uvar;
|
Entity *uvar = entry.uvar;
|
||||||
Entity *prev = scope_insert_no_mutex(ctx->scope, uvar);
|
Entity *prev = scope_insert_no_mutex(ctx->scope, uvar);
|
||||||
@@ -1506,6 +1509,7 @@ gb_internal bool check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *de
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
rw_mutex_unlock(&ctx->scope->mutex);
|
||||||
|
|
||||||
|
|
||||||
bool where_clause_ok = evaluate_where_clauses(ctx, nullptr, decl->scope, &decl->proc_lit->ProcLit.where_clauses, !decl->where_clauses_evaluated);
|
bool where_clause_ok = evaluate_where_clauses(ctx, nullptr, decl->scope, &decl->proc_lit->ProcLit.where_clauses, !decl->where_clauses_evaluated);
|
||||||
|
|||||||
+3
-1
@@ -236,10 +236,12 @@ gb_internal void check_did_you_mean_scope(String const &name, Scope *scope, char
|
|||||||
DidYouMeanAnswers d = did_you_mean_make(heap_allocator(), scope->elements.entries.count, name);
|
DidYouMeanAnswers d = did_you_mean_make(heap_allocator(), scope->elements.entries.count, name);
|
||||||
defer (did_you_mean_destroy(&d));
|
defer (did_you_mean_destroy(&d));
|
||||||
|
|
||||||
MUTEX_GUARD_BLOCK(&scope->mutex) for (auto const &entry : scope->elements) {
|
rw_mutex_shared_lock(&scope->mutex);
|
||||||
|
for (auto const &entry : scope->elements) {
|
||||||
Entity *e = entry.value;
|
Entity *e = entry.value;
|
||||||
did_you_mean_append(&d, e->token.string);
|
did_you_mean_append(&d, e->token.string);
|
||||||
}
|
}
|
||||||
|
rw_mutex_shared_unlock(&scope->mutex);
|
||||||
check_did_you_mean_print(&d, prefix);
|
check_did_you_mean_print(&d, prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-1
@@ -622,7 +622,10 @@ gb_internal bool check_using_stmt_entity(CheckerContext *ctx, AstUsingStmt *us,
|
|||||||
|
|
||||||
case Entity_ImportName: {
|
case Entity_ImportName: {
|
||||||
Scope *scope = e->ImportName.scope;
|
Scope *scope = e->ImportName.scope;
|
||||||
MUTEX_GUARD_BLOCK(scope->mutex) for (auto const &entry : scope->elements) {
|
rw_mutex_lock(&scope->mutex);
|
||||||
|
defer (rw_mutex_unlock(&scope->mutex));
|
||||||
|
|
||||||
|
for (auto const &entry : scope->elements) {
|
||||||
String name = entry.key.string;
|
String name = entry.key.string;
|
||||||
Entity *decl = entry.value;
|
Entity *decl = entry.value;
|
||||||
if (!is_entity_exported(decl)) continue;
|
if (!is_entity_exported(decl)) continue;
|
||||||
|
|||||||
+13
-8
@@ -51,10 +51,11 @@ gb_internal bool check_rtti_type_disallowed(Ast *expr, Type *type, char const *f
|
|||||||
gb_internal void scope_reset(Scope *scope) {
|
gb_internal void scope_reset(Scope *scope) {
|
||||||
if (scope == nullptr) return;
|
if (scope == nullptr) return;
|
||||||
|
|
||||||
MUTEX_GUARD(&scope->mutex);
|
rw_mutex_lock(&scope->mutex);
|
||||||
scope->head_child.store(nullptr, std::memory_order_relaxed);
|
scope->head_child.store(nullptr, std::memory_order_relaxed);
|
||||||
string_map_clear(&scope->elements);
|
string_map_clear(&scope->elements);
|
||||||
ptr_set_clear(&scope->imported);
|
ptr_set_clear(&scope->imported);
|
||||||
|
rw_mutex_unlock(&scope->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_internal void scope_reserve(Scope *scope, isize capacity) {
|
gb_internal void scope_reserve(Scope *scope, isize capacity) {
|
||||||
@@ -180,9 +181,9 @@ gb_internal void init_decl_info(DeclInfo *d, Scope *scope, DeclInfo *parent) {
|
|||||||
gb_zero_item(d);
|
gb_zero_item(d);
|
||||||
d->parent = parent;
|
d->parent = parent;
|
||||||
d->scope = scope;
|
d->scope = scope;
|
||||||
ptr_set_init(&d->deps);
|
ptr_set_init(&d->deps, 0);
|
||||||
ptr_set_init(&d->type_info_deps);
|
ptr_set_init(&d->type_info_deps, 0);
|
||||||
array_init (&d->labels, heap_allocator());
|
d->labels.allocator = heap_allocator();
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_internal DeclInfo *make_decl_info(Scope *scope, DeclInfo *parent) {
|
gb_internal DeclInfo *make_decl_info(Scope *scope, DeclInfo *parent) {
|
||||||
@@ -394,9 +395,9 @@ gb_internal void scope_lookup_parent(Scope *scope, String const &name, Scope **s
|
|||||||
StringHashKey key = string_hash_string(name);
|
StringHashKey key = string_hash_string(name);
|
||||||
for (Scope *s = scope; s != nullptr; s = s->parent) {
|
for (Scope *s = scope; s != nullptr; s = s->parent) {
|
||||||
Entity **found = nullptr;
|
Entity **found = nullptr;
|
||||||
mutex_lock(&s->mutex);
|
rw_mutex_shared_lock(&s->mutex);
|
||||||
found = string_map_get(&s->elements, key);
|
found = string_map_get(&s->elements, key);
|
||||||
mutex_unlock(&s->mutex);
|
rw_mutex_shared_unlock(&s->mutex);
|
||||||
if (found) {
|
if (found) {
|
||||||
Entity *e = *found;
|
Entity *e = *found;
|
||||||
if (gone_thru_proc) {
|
if (gone_thru_proc) {
|
||||||
@@ -482,7 +483,7 @@ gb_internal Entity *scope_insert_with_name(Scope *s, String const &name, Entity
|
|||||||
Entity **found = nullptr;
|
Entity **found = nullptr;
|
||||||
Entity *result = nullptr;
|
Entity *result = nullptr;
|
||||||
|
|
||||||
MUTEX_GUARD(&s->mutex);
|
rw_mutex_lock(&s->mutex);
|
||||||
|
|
||||||
found = string_map_get(&s->elements, key);
|
found = string_map_get(&s->elements, key);
|
||||||
|
|
||||||
@@ -509,6 +510,8 @@ gb_internal Entity *scope_insert_with_name(Scope *s, String const &name, Entity
|
|||||||
entity->scope = s;
|
entity->scope = s;
|
||||||
}
|
}
|
||||||
end:;
|
end:;
|
||||||
|
rw_mutex_unlock(&s->mutex);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -669,7 +672,8 @@ gb_internal void check_scope_usage(Checker *c, Scope *scope) {
|
|||||||
Array<VettedEntity> vetted_entities = {};
|
Array<VettedEntity> vetted_entities = {};
|
||||||
array_init(&vetted_entities, heap_allocator());
|
array_init(&vetted_entities, heap_allocator());
|
||||||
|
|
||||||
MUTEX_GUARD_BLOCK(scope->mutex) for (auto const &entry : scope->elements) {
|
rw_mutex_shared_lock(&scope->mutex);
|
||||||
|
for (auto const &entry : scope->elements) {
|
||||||
Entity *e = entry.value;
|
Entity *e = entry.value;
|
||||||
if (e == nullptr) continue;
|
if (e == nullptr) continue;
|
||||||
VettedEntity ve_unused = {};
|
VettedEntity ve_unused = {};
|
||||||
@@ -686,6 +690,7 @@ gb_internal void check_scope_usage(Checker *c, Scope *scope) {
|
|||||||
array_add(&vetted_entities, ve_shadowed);
|
array_add(&vetted_entities, ve_shadowed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
rw_mutex_shared_unlock(&scope->mutex);
|
||||||
|
|
||||||
gb_sort(vetted_entities.data, vetted_entities.count, gb_size_of(VettedEntity), vetted_entity_variable_pos_cmp);
|
gb_sort(vetted_entities.data, vetted_entities.count, gb_size_of(VettedEntity), vetted_entity_variable_pos_cmp);
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -224,7 +224,7 @@ struct Scope {
|
|||||||
std::atomic<Scope *> next;
|
std::atomic<Scope *> next;
|
||||||
std::atomic<Scope *> head_child;
|
std::atomic<Scope *> head_child;
|
||||||
|
|
||||||
BlockingMutex mutex;
|
RwMutex mutex;
|
||||||
StringMap<Entity *> elements;
|
StringMap<Entity *> elements;
|
||||||
PtrSet<Scope *> imported;
|
PtrSet<Scope *> imported;
|
||||||
|
|
||||||
|
|||||||
+13
-14
@@ -47,7 +47,7 @@ gb_internal void thread_pool_destroy(ThreadPool *pool) {
|
|||||||
|
|
||||||
for_array_off(i, 1, pool->threads) {
|
for_array_off(i, 1, pool->threads) {
|
||||||
Thread *t = &pool->threads[i];
|
Thread *t = &pool->threads[i];
|
||||||
pool->tasks_available.fetch_add(1, std::memory_order_release);
|
pool->tasks_available.fetch_add(1, std::memory_order_relaxed);
|
||||||
futex_broadcast(&pool->tasks_available);
|
futex_broadcast(&pool->tasks_available);
|
||||||
thread_join_and_destroy(t);
|
thread_join_and_destroy(t);
|
||||||
}
|
}
|
||||||
@@ -74,7 +74,7 @@ void thread_pool_queue_push(Thread *thread, WorkerTask task) {
|
|||||||
} while (!thread->head_and_tail.compare_exchange_weak(capture, new_capture));
|
} while (!thread->head_and_tail.compare_exchange_weak(capture, new_capture));
|
||||||
|
|
||||||
thread->pool->tasks_left.fetch_add(1, std::memory_order_release);
|
thread->pool->tasks_left.fetch_add(1, std::memory_order_release);
|
||||||
thread->pool->tasks_available.fetch_add(1, std::memory_order_release);
|
thread->pool->tasks_available.fetch_add(1, std::memory_order_relaxed);
|
||||||
futex_broadcast(&thread->pool->tasks_available);
|
futex_broadcast(&thread->pool->tasks_available);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ bool thread_pool_queue_pop(Thread *thread, WorkerTask *task) {
|
|||||||
u64 capture;
|
u64 capture;
|
||||||
u64 new_capture;
|
u64 new_capture;
|
||||||
do {
|
do {
|
||||||
capture = thread->head_and_tail.load();
|
capture = thread->head_and_tail.load(std::memory_order_acquire);
|
||||||
|
|
||||||
u64 mask = thread->capacity - 1;
|
u64 mask = thread->capacity - 1;
|
||||||
u64 head = (capture >> 32) & mask;
|
u64 head = (capture >> 32) & mask;
|
||||||
@@ -97,7 +97,7 @@ bool thread_pool_queue_pop(Thread *thread, WorkerTask *task) {
|
|||||||
*task = thread->queue[tail];
|
*task = thread->queue[tail];
|
||||||
|
|
||||||
new_capture = (head << 32) | new_tail;
|
new_capture = (head << 32) | new_tail;
|
||||||
} while (!thread->head_and_tail.compare_exchange_weak(capture, new_capture));
|
} while (!thread->head_and_tail.compare_exchange_weak(capture, new_capture, std::memory_order_release));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -168,22 +168,21 @@ gb_internal THREAD_PROC(thread_pool_thread_proc) {
|
|||||||
|
|
||||||
Thread *thread = &pool->threads.data[idx];
|
Thread *thread = &pool->threads.data[idx];
|
||||||
WorkerTask task;
|
WorkerTask task;
|
||||||
if (!thread_pool_queue_pop(thread, &task)) {
|
if (thread_pool_queue_pop(thread, &task)) {
|
||||||
continue;
|
task.do_work(task.data);
|
||||||
}
|
pool->tasks_left.fetch_sub(1, std::memory_order_release);
|
||||||
task.do_work(task.data);
|
|
||||||
pool->tasks_left.fetch_sub(1, std::memory_order_release);
|
|
||||||
|
|
||||||
if (pool->tasks_left.load(std::memory_order_acquire) == 0) {
|
if (pool->tasks_left.load(std::memory_order_acquire) == 0) {
|
||||||
futex_signal(&pool->tasks_left);
|
futex_signal(&pool->tasks_left);
|
||||||
}
|
}
|
||||||
|
|
||||||
goto main_loop_continue;
|
goto main_loop_continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we've done all our work, and there's nothing to steal, go to sleep
|
// if we've done all our work, and there's nothing to steal, go to sleep
|
||||||
state = pool->tasks_available.load();
|
state = pool->tasks_available.load(std::memory_order_acquire);
|
||||||
futex_wait(&pool->tasks_available, state);
|
futex_wait(&pool->tasks_available, state);
|
||||||
|
|
||||||
main_loop_continue:;
|
main_loop_continue:;
|
||||||
|
|||||||
@@ -8,10 +8,12 @@
|
|||||||
|
|
||||||
struct BlockingMutex;
|
struct BlockingMutex;
|
||||||
struct RecursiveMutex;
|
struct RecursiveMutex;
|
||||||
|
struct RwMutex;
|
||||||
struct Semaphore;
|
struct Semaphore;
|
||||||
struct Condition;
|
struct Condition;
|
||||||
struct Thread;
|
struct Thread;
|
||||||
struct ThreadPool;
|
struct ThreadPool;
|
||||||
|
struct Parker;
|
||||||
|
|
||||||
#define THREAD_PROC(name) isize name(struct Thread *thread)
|
#define THREAD_PROC(name) isize name(struct Thread *thread)
|
||||||
gb_internal THREAD_PROC(thread_pool_thread_proc);
|
gb_internal THREAD_PROC(thread_pool_thread_proc);
|
||||||
@@ -56,6 +58,13 @@ gb_internal void mutex_lock (RecursiveMutex *m);
|
|||||||
gb_internal bool mutex_try_lock(RecursiveMutex *m);
|
gb_internal bool mutex_try_lock(RecursiveMutex *m);
|
||||||
gb_internal void mutex_unlock (RecursiveMutex *m);
|
gb_internal void mutex_unlock (RecursiveMutex *m);
|
||||||
|
|
||||||
|
gb_internal void rw_mutex_lock (RwMutex *m);
|
||||||
|
gb_internal bool rw_mutex_try_lock (RwMutex *m);
|
||||||
|
gb_internal void rw_mutex_unlock (RwMutex *m);
|
||||||
|
gb_internal void rw_mutex_shared_lock (RwMutex *m);
|
||||||
|
gb_internal bool rw_mutex_try_shared_lock(RwMutex *m);
|
||||||
|
gb_internal void rw_mutex_shared_unlock (RwMutex *m);
|
||||||
|
|
||||||
gb_internal void semaphore_post (Semaphore *s, i32 count);
|
gb_internal void semaphore_post (Semaphore *s, i32 count);
|
||||||
gb_internal void semaphore_wait (Semaphore *s);
|
gb_internal void semaphore_wait (Semaphore *s);
|
||||||
gb_internal void semaphore_release(Semaphore *s) { semaphore_post(s, 1); }
|
gb_internal void semaphore_release(Semaphore *s) { semaphore_post(s, 1); }
|
||||||
@@ -65,6 +74,10 @@ gb_internal void condition_broadcast(Condition *c);
|
|||||||
gb_internal void condition_signal(Condition *c);
|
gb_internal void condition_signal(Condition *c);
|
||||||
gb_internal void condition_wait(Condition *c, BlockingMutex *m);
|
gb_internal void condition_wait(Condition *c, BlockingMutex *m);
|
||||||
|
|
||||||
|
gb_internal void park(Parker *p);
|
||||||
|
gb_internal void unpark_one(Parker *p);
|
||||||
|
gb_internal void unpark_all(Parker *p);
|
||||||
|
|
||||||
gb_internal u32 thread_current_id(void);
|
gb_internal u32 thread_current_id(void);
|
||||||
|
|
||||||
gb_internal void thread_init (ThreadPool *pool, Thread *t, isize idx);
|
gb_internal void thread_init (ThreadPool *pool, Thread *t, isize idx);
|
||||||
@@ -205,6 +218,30 @@ gb_internal void semaphore_wait(Semaphore *s) {
|
|||||||
gb_internal void condition_wait(Condition *c, BlockingMutex *m) {
|
gb_internal void condition_wait(Condition *c, BlockingMutex *m) {
|
||||||
SleepConditionVariableSRW(&c->cond, &m->srwlock, INFINITE, 0);
|
SleepConditionVariableSRW(&c->cond, &m->srwlock, INFINITE, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct RwMutex {
|
||||||
|
SRWLOCK srwlock;
|
||||||
|
};
|
||||||
|
|
||||||
|
gb_internal void rw_mutex_lock(RwMutex *m) {
|
||||||
|
AcquireSRWLockExclusive(&m->srwlock);
|
||||||
|
}
|
||||||
|
gb_internal bool rw_mutex_try_lock(RwMutex *m) {
|
||||||
|
return !!TryAcquireSRWLockExclusive(&m->srwlock);
|
||||||
|
}
|
||||||
|
gb_internal void rw_mutex_unlock(RwMutex *m) {
|
||||||
|
ReleaseSRWLockExclusive(&m->srwlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
gb_internal void rw_mutex_shared_lock(RwMutex *m) {
|
||||||
|
AcquireSRWLockShared(&m->srwlock);
|
||||||
|
}
|
||||||
|
gb_internal bool rw_mutex_try_shared_lock(RwMutex *m) {
|
||||||
|
return !!TryAcquireSRWLockShared(&m->srwlock);
|
||||||
|
}
|
||||||
|
gb_internal void rw_mutex_shared_unlock(RwMutex *m) {
|
||||||
|
ReleaseSRWLockShared(&m->srwlock);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
enum Internal_Mutex_State : i32 {
|
enum Internal_Mutex_State : i32 {
|
||||||
Internal_Mutex_State_Unlocked = 0,
|
Internal_Mutex_State_Unlocked = 0,
|
||||||
@@ -306,8 +343,67 @@ gb_internal void semaphore_wait(Semaphore *s) {
|
|||||||
futex_wait(&c->state(), state);
|
futex_wait(&c->state(), state);
|
||||||
mutex_lock(m);
|
mutex_lock(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct RwMutex {
|
||||||
|
// TODO(bill): make this a proper RW mutex
|
||||||
|
BlockingMutex mutex;
|
||||||
|
};
|
||||||
|
|
||||||
|
gb_internal void rw_mutex_lock(RwMutex *m) {
|
||||||
|
mutex_lock(&m->mutex);
|
||||||
|
}
|
||||||
|
gb_internal bool rw_mutex_try_lock(RwMutex *m) {
|
||||||
|
return mutex_try_lock(&m->mutex);
|
||||||
|
}
|
||||||
|
gb_internal void rw_mutex_unlock(RwMutex *m) {
|
||||||
|
mutex_unlock(&m->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
gb_internal void rw_mutex_shared_lock(RwMutex *m) {
|
||||||
|
mutex_lock(&m->mutex);
|
||||||
|
}
|
||||||
|
gb_internal bool rw_mutex_try_shared_lock(RwMutex *m) {
|
||||||
|
return mutex_try_lock(&m->mutex);
|
||||||
|
}
|
||||||
|
gb_internal void rw_mutex_shared_unlock(RwMutex *m) {
|
||||||
|
mutex_unlock(&m->mutex);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct Parker {
|
||||||
|
Futex state;
|
||||||
|
};
|
||||||
|
enum ParkerState : u32 {
|
||||||
|
ParkerState_Empty = 0,
|
||||||
|
ParkerState_Notified = 1,
|
||||||
|
ParkerState_Parked = UINT32_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
gb_internal void park(Parker *p) {
|
||||||
|
if (p->state.fetch_sub(1, std::memory_order_acquire) == ParkerState_Notified) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (;;) {
|
||||||
|
futex_wait(&p->state, ParkerState_Parked);
|
||||||
|
i32 notified = ParkerState_Empty;
|
||||||
|
if (p->state.compare_exchange_strong(notified, ParkerState_Empty, std::memory_order_acquire, std::memory_order_acquire)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gb_internal void unpark_one(Parker *p) {
|
||||||
|
if (p->state.exchange(ParkerState_Notified, std::memory_order_release) == ParkerState_Parked) {
|
||||||
|
futex_signal(&p->state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gb_internal void unpark_all(Parker *p) {
|
||||||
|
if (p->state.exchange(ParkerState_Notified, std::memory_order_release) == ParkerState_Parked) {
|
||||||
|
futex_broadcast(&p->state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
gb_internal u32 thread_current_id(void) {
|
gb_internal u32 thread_current_id(void) {
|
||||||
u32 thread_id;
|
u32 thread_id;
|
||||||
|
|||||||
Reference in New Issue
Block a user