Browse Source

Fix bugs in `RID_Alloc`

- Replace unintended `%` with `&`
- `get_owned_list()`: make thread-safe and fix logic
- Apply same logic fix to the destructor

Previously, the determination of owned RIDs was wrong. For instance, it could skip owned items or include duplicates in the list.

Avoids the engine crashing at exit.
Pedro J. Estébanez 6 năm trước cách đây
mục cha
commit
e38ae8d7e4
1 tập tin đã thay đổi với 17 bổ sung8 xóa
  1. 17 8
      core/rid_owner.h

+ 17 - 8
core/rid_owner.h

@@ -85,7 +85,7 @@ public:
 		T *ptr = &chunks[free_chunk][free_element];
 		memnew_placement(ptr, T(p_value));
 
-		uint32_t validator = (uint32_t)(_gen_id() % 0xFFFFFFFF);
+		uint32_t validator = (uint32_t)(_gen_id() & 0xFFFFFFFF);
 		uint64_t id = validator;
 		id <<= 32;
 		id |= free_index;
@@ -234,10 +234,17 @@ public:
 	}
 
 	void get_owned_list(List<RID> *p_owned) {
-		for (size_t i = 0; i < alloc_count; i++) {
-			uint64_t idx = free_list_chunks[i / elements_in_chunk][i % elements_in_chunk];
-			uint64_t validator = validator_chunks[idx / elements_in_chunk][idx % elements_in_chunk];
-			p_owned->push_back(_make_from_id((validator << 32) | idx));
+		if (THREAD_SAFE) {
+			spin_lock.lock();
+		}
+		for (size_t i = 0; i < max_alloc; i++) {
+			uint64_t validator = validator_chunks[i / elements_in_chunk][i % elements_in_chunk];
+			if (validator != 0xFFFFFFFF) {
+				p_owned->push_back(_make_from_id((validator << 32) | i));
+			}
+		}
+		if (THREAD_SAFE) {
+			spin_lock.unlock();
 		}
 	}
 
@@ -264,9 +271,11 @@ public:
 				print_error("ERROR: " + itos(alloc_count) + " RID allocations of type '" + typeid(T).name() + "' were leaked at exit.");
 			}
 
-			for (uint32_t i = 0; i < alloc_count; i++) {
-				uint64_t idx = free_list_chunks[i / elements_in_chunk][i % elements_in_chunk];
-				chunks[idx / elements_in_chunk][idx % elements_in_chunk].~T();
+			for (size_t i = 0; i < max_alloc; i++) {
+				uint64_t validator = validator_chunks[i / elements_in_chunk][i % elements_in_chunk];
+				if (validator != 0xFFFFFFFF) {
+					chunks[i / elements_in_chunk][i % elements_in_chunk].~T();
+				}
 			}
 		}