Browse Source

Add mutex guards for signature scopes

gingerBill 3 years ago
parent
commit
7cc265e14c
7 changed files with 67 additions and 13 deletions
  1. 4 0
      src/array.cpp
  2. 1 1
      src/check_decl.cpp
  3. 2 0
      src/check_expr.cpp
  4. 1 1
      src/check_stmt.cpp
  5. 1 1
      src/checker.cpp
  6. 24 10
      src/common_memory.cpp
  7. 34 0
      src/threading.cpp

+ 4 - 0
src/array.cpp

@@ -77,15 +77,19 @@ template <typename T> Slice<T> slice_from_array(Array<T> const &a);
 
 
 template <typename T>
 template <typename T>
 Slice<T> slice_make(gbAllocator const &allocator, isize count) {
 Slice<T> slice_make(gbAllocator const &allocator, isize count) {
+	GB_ASSERT(count >= 0);
 	Slice<T> s = {};
 	Slice<T> s = {};
 	s.data = gb_alloc_array(allocator, T, count);
 	s.data = gb_alloc_array(allocator, T, count);
+	GB_ASSERT(s.data != nullptr);
 	s.count = count;
 	s.count = count;
 	return s;
 	return s;
 }
 }
 
 
 template <typename T>
 template <typename T>
 void slice_init(Slice<T> *s, gbAllocator const &allocator, isize count) {
 void slice_init(Slice<T> *s, gbAllocator const &allocator, isize count) {
+	GB_ASSERT(count >= 0);
 	s->data = gb_alloc_array(allocator, T, count);
 	s->data = gb_alloc_array(allocator, T, count);
+	GB_ASSERT(s->data != nullptr);
 	s->count = count;
 	s->count = count;
 }
 }
 
 

+ 1 - 1
src/check_decl.cpp

@@ -1286,7 +1286,7 @@ void check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *decl, Type *ty
 	using_entities.allocator = heap_allocator();
 	using_entities.allocator = heap_allocator();
 	defer (array_free(&using_entities));
 	defer (array_free(&using_entities));
 
 
-	{
+	MUTEX_GUARD_BLOCK(ctx->scope->mutex) {
 		if (type->Proc.param_count > 0) {
 		if (type->Proc.param_count > 0) {
 			TypeTuple *params = &type->Proc.params->Tuple;
 			TypeTuple *params = &type->Proc.params->Tuple;
 			for_array(i, params->variables) {
 			for_array(i, params->variables) {

+ 2 - 0
src/check_expr.cpp

@@ -4021,10 +4021,12 @@ void check_did_you_mean_scope(String const &name, Scope *scope) {
 	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_lock(&scope->mutex);
 	for_array(i, scope->elements.entries) {
 	for_array(i, scope->elements.entries) {
 		Entity *e = scope->elements.entries[i].value;
 		Entity *e = scope->elements.entries[i].value;
 		did_you_mean_append(&d, e->token.string);
 		did_you_mean_append(&d, e->token.string);
 	}
 	}
+	mutex_unlock(&scope->mutex);
 	check_did_you_mean_print(&d);
 	check_did_you_mean_print(&d);
 }
 }
 
 

+ 1 - 1
src/check_stmt.cpp

@@ -607,7 +607,7 @@ bool check_using_stmt_entity(CheckerContext *ctx, AstUsingStmt *us, Ast *expr, b
 
 
 	case Entity_ImportName: {
 	case Entity_ImportName: {
 		Scope *scope = e->ImportName.scope;
 		Scope *scope = e->ImportName.scope;
-		for_array(i, scope->elements.entries) {
+		MUTEX_GUARD_BLOCK(scope->mutex) for_array(i, scope->elements.entries) {
 			String name = scope->elements.entries[i].key.string;
 			String name = scope->elements.entries[i].key.string;
 			Entity *decl = scope->elements.entries[i].value;
 			Entity *decl = scope->elements.entries[i].value;
 			if (!is_entity_exported(decl)) continue;
 			if (!is_entity_exported(decl)) continue;

+ 1 - 1
src/checker.cpp

@@ -622,7 +622,7 @@ 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());
 
 
-	for_array(i, scope->elements.entries) {
+	MUTEX_GUARD_BLOCK(scope->mutex) for_array(i, scope->elements.entries) {
 		Entity *e = scope->elements.entries[i].value;
 		Entity *e = scope->elements.entries[i].value;
 		if (e == nullptr) continue;
 		if (e == nullptr) continue;
 		VettedEntity ve = {};
 		VettedEntity ve = {};

+ 24 - 10
src/common_memory.cpp

@@ -325,18 +325,32 @@ GB_ALLOCATOR_PROC(heap_allocator_proc) {
 // TODO(bill): Throughly test!
 // TODO(bill): Throughly test!
 	switch (type) {
 	switch (type) {
 #if defined(GB_COMPILER_MSVC)
 #if defined(GB_COMPILER_MSVC)
-	case gbAllocation_Alloc: {
-		isize aligned_size = align_formula_isize(size, alignment);
-		// TODO(bill): Make sure this is aligned correctly
-		ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, aligned_size);
-	} break;
+	case gbAllocation_Alloc:
+		if (size == 0) {
+			return NULL;
+		} else {
+			isize aligned_size = align_formula_isize(size, alignment);
+			// TODO(bill): Make sure this is aligned correctly
+			ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, aligned_size);
+		}
+		break;
 	case gbAllocation_Free:
 	case gbAllocation_Free:
-		HeapFree(GetProcessHeap(), 0, old_memory);
+		if (old_memory != nullptr) {
+			HeapFree(GetProcessHeap(), 0, old_memory);
+		}
+		break;
+	case gbAllocation_Resize:
+		if (old_memory != nullptr && size > 0) {
+			isize aligned_size = align_formula_isize(size, alignment);
+			ptr = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, old_memory, aligned_size);
+		} else if (old_memory != nullptr) {
+			HeapFree(GetProcessHeap(), 0, old_memory);
+		} else if (size != 0) {
+			isize aligned_size = align_formula_isize(size, alignment);
+			// TODO(bill): Make sure this is aligned correctly
+			ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, aligned_size);
+		}
 		break;
 		break;
-	case gbAllocation_Resize: {
-		isize aligned_size = align_formula_isize(size, alignment);
-		ptr = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, old_memory, aligned_size);
-	} break;
 #elif defined(GB_SYSTEM_LINUX)
 #elif defined(GB_SYSTEM_LINUX)
 	// TODO(bill): *nix version that's decent
 	// TODO(bill): *nix version that's decent
 	case gbAllocation_Alloc: {
 	case gbAllocation_Alloc: {

+ 34 - 0
src/threading.cpp

@@ -68,6 +68,40 @@ void yield_thread(void);
 void yield_process(void);
 void yield_process(void);
 
 
 
 
+struct MutexGuard {
+	MutexGuard() = delete;
+	MutexGuard(MutexGuard const &) = delete;
+
+	MutexGuard(BlockingMutex *bm) : bm{bm} {
+		mutex_lock(this->bm);
+	}
+	MutexGuard(RecursiveMutex *rm) : rm{rm} {
+		mutex_lock(this->rm);
+	}
+	MutexGuard(BlockingMutex &bm) : bm{&bm} {
+		mutex_lock(this->bm);
+	}
+	MutexGuard(RecursiveMutex &rm) : rm{&rm} {
+		mutex_lock(this->rm);
+	}
+	~MutexGuard() {
+		if (this->bm) {
+			mutex_unlock(this->bm);
+		} else if (this->rm) {
+			mutex_unlock(this->rm);
+		}
+	}
+
+	operator bool() const { return true; }
+
+	BlockingMutex *bm;
+	RecursiveMutex *rm;
+};
+
+#define MUTEX_GUARD_BLOCK(m) if (MutexGuard GB_DEFER_3(_mutex_guard_) = m)
+#define MUTEX_GUARD(m) MutexGuard GB_DEFER_3(_mutex_guard_) = m
+
+
 #if defined(GB_SYSTEM_WINDOWS)
 #if defined(GB_SYSTEM_WINDOWS)
 	struct BlockingMutex {
 	struct BlockingMutex {
 		SRWLOCK srwlock;
 		SRWLOCK srwlock;