static void* objectmap_thread(void* arg) { objectmap_t* map; object_base_t* objects; int obj; int loop; object_base_t* lookup; map = arg; objects = memory_allocate(0, sizeof(object_base_t) * 512, 16, MEMORY_PERSISTENT | MEMORY_ZERO_INITIALIZED); thread_sleep(10); for (loop = 0; loop < 32; ++loop) { thread_yield(); for (obj = 0; obj < 512; ++obj) { atomic_store32(&objects[obj].ref, 1); objects[obj].id = objectmap_reserve(map); EXPECT_NE_MSGFORMAT(objects[obj].id, 0, "Unable to reserve slot for object num %d", obj); EXPECT_EQ_MSGFORMAT(objectmap_lookup(map, objects[obj].id), 0, "Object %d (%" PRIx64 ") already stored in map in loop %d", obj, objects[obj].id, loop); EXPECT_TRUE(objectmap_set(map, objects[obj].id, objects + obj)); lookup = objectmap_lookup(map, objects[obj].id); EXPECT_NE_MSGFORMAT(lookup, 0, "Object num %d (%" PRIx64 ") not set in map, got null on lookup in loop %d", obj, objects[obj].id, loop); EXPECT_EQ_MSGFORMAT(lookup, objects + obj, "Object %d (%" PRIx64 ") 0x%" PRIfixPTR " was not set at reserved slot in map, got object 0x%" PRIfixPTR " in loop %d", obj, objects[obj].id, (uintptr_t)(objects + obj), (uintptr_t)lookup, loop); } thread_yield(); for (obj = 0; obj < 512; ++obj) { void* raw = map->map[ objects[obj].id & map->mask_index ]; lookup = objectmap_lookup(map, objects[obj].id); EXPECT_NE_MSGFORMAT(lookup, 0, "Object 0x%" PRIfixPTR " num %d (%" PRIx64 ") not set in map, got null on lookup in loop %d (raw 0x%" PRIfixPTR ")", (uintptr_t)(objects + obj), obj, objects[obj].id, loop, (uintptr_t)raw); EXPECT_EQ_MSGFORMAT(lookup, objects + obj, "Object %d (%" PRIx64 ") 0x%" PRIfixPTR " was not set at reserved slot in map, got object 0x%" PRIfixPTR " in loop %d", obj, objects[obj].id, (uintptr_t)(objects + obj), (uintptr_t)lookup, loop); EXPECT_TRUE(objectmap_free(map, objects[obj].id)); lookup = objectmap_lookup(map, objects[obj].id); EXPECT_EQ_MSGFORMAT(lookup, 0, "Object %d (%" PRIx64 ") 0x%" PRIfixPTR " still set in map, got non-null (0x%" PRIfixPTR ") on lookup in loop %d", obj, objects[obj].id, (uintptr_t)(objects + obj), (uintptr_t)lookup, loop); } } memory_deallocate(objects); return 0; }
static void _library_destroy( library_t* library ) { objectmap_free( _library_map, library->id ); #if FOUNDATION_PLATFORM_WINDOWS FreeLibrary( library->dll ); #elif FOUNDATION_PLATFORM_POSIX dlclose( library->lib ); #endif memory_deallocate( library ); }
void render_buffer_destroy(object_t id) { int32_t ref; render_buffer_t* buffer = GET_BUFFER(id); if (buffer) { do { ref = atomic_load32(&buffer->ref); if ((ref > 0) && atomic_cas32(&buffer->ref, ref - 1, ref)) { if (ref == 1) { objectmap_free(_render_map_buffer, id); buffer->backend->vtable.deallocate_buffer(buffer->backend, buffer, true, true); memory_deallocate(buffer); } return; } } while (ref > 0); } }
DECLARE_TEST(objectmap, store) { objectmap_t* map; object_base_t first; object_base_t second; object_base_t third; map = objectmap_allocate(129); memset(&first, 0, sizeof(first)); memset(&second, 0, sizeof(first)); memset(&third, 0, sizeof(first)); atomic_store32(&first.ref, 1); atomic_store32(&second.ref, 1); atomic_store32(&third.ref, 1); first.id = 1; second.id = 2; third.id = 3; EXPECT_EQ(objectmap_lookup(map, 0), 0); EXPECT_EQ(objectmap_lookup(map, 1), 0); first.id = objectmap_reserve(map); EXPECT_EQ(objectmap_lookup(map, first.id), 0); EXPECT_EQ(objectmap_raw_lookup(map, 0), 0); second.id = objectmap_reserve(map); EXPECT_EQ(objectmap_lookup(map, first.id), 0); EXPECT_EQ(objectmap_raw_lookup(map, 0), 0); EXPECT_EQ(objectmap_lookup(map, second.id), 0); EXPECT_EQ(objectmap_raw_lookup(map, 1), 0); objectmap_set(map, first.id, &first); EXPECT_EQ(objectmap_lookup(map, first.id), &first); EXPECT_EQ(objectmap_raw_lookup(map, 0), &first); EXPECT_EQ(objectmap_lookup(map, second.id), 0); EXPECT_EQ(objectmap_raw_lookup(map, 1), 0); objectmap_set(map, second.id, &second); EXPECT_EQ(objectmap_lookup(map, first.id), &first); EXPECT_EQ(objectmap_raw_lookup(map, 0), &first); EXPECT_EQ(objectmap_lookup(map, second.id), &second); EXPECT_EQ(objectmap_raw_lookup(map, 1), &second); objectmap_free(map, first.id); EXPECT_EQ(objectmap_lookup(map, first.id), 0); EXPECT_EQ(objectmap_raw_lookup(map, 0), 0); EXPECT_EQ(objectmap_lookup(map, second.id), &second); EXPECT_EQ(objectmap_raw_lookup(map, 1), &second); objectmap_free(map, first.id); EXPECT_EQ(objectmap_lookup(map, first.id), 0); EXPECT_EQ(objectmap_raw_lookup(map, 0), 0); EXPECT_EQ(objectmap_lookup(map, second.id), &second); EXPECT_EQ(objectmap_raw_lookup(map, 1), &second); objectmap_free(map, second.id); EXPECT_EQ(objectmap_lookup(map, first.id), 0); EXPECT_EQ(objectmap_raw_lookup(map, 0), 0); EXPECT_EQ(objectmap_lookup(map, second.id), 0); EXPECT_EQ(objectmap_raw_lookup(map, 1), 0); objectmap_deallocate(map); //Size should be clamped to three map = objectmap_allocate(1); EXPECT_EQ(objectmap_lookup(map, 0), 0); EXPECT_EQ(objectmap_lookup(map, 1), 0); first.id = objectmap_reserve(map); EXPECT_TYPENE(first.id, 0, object_t, PRIx64); EXPECT_EQ(objectmap_lookup(map, first.id), 0); EXPECT_EQ(objectmap_raw_lookup(map, 0), 0); second.id = objectmap_reserve(map); EXPECT_TYPENE(second.id, 0, object_t, PRIx64); EXPECT_EQ(objectmap_lookup(map, first.id), 0); EXPECT_EQ(objectmap_raw_lookup(map, 0), 0); EXPECT_EQ(objectmap_lookup(map, second.id), 0); EXPECT_EQ(objectmap_raw_lookup(map, 1), 0); third.id = objectmap_reserve(map); EXPECT_TYPENE(third.id, 0, object_t, PRIx64); EXPECT_EQ(objectmap_lookup(map, first.id), 0); EXPECT_EQ(objectmap_raw_lookup(map, 0), 0); EXPECT_EQ(objectmap_lookup(map, second.id), 0); EXPECT_EQ(objectmap_raw_lookup(map, 1), 0); EXPECT_EQ(objectmap_lookup(map, third.id), 0); EXPECT_EQ(objectmap_raw_lookup(map, 1), 0); objectmap_set(map, first.id, &first); objectmap_set(map, second.id, &second); objectmap_set(map, third.id, &third); log_enable_stdout(false); EXPECT_TYPEEQ(objectmap_reserve(map), 0, object_t, PRIx64); EXPECT_TYPEEQ(objectmap_reserve(map), 0, object_t, PRIx64); log_enable_stdout(true); objectmap_free(map, first.id); objectmap_free(map, second.id); //Leak one object //objectmap_free(map, third.id); EXPECT_EQ(objectmap_lookup_ref(map, first.id), nullptr); EXPECT_EQ(objectmap_raw_lookup(map, 0), 0); EXPECT_EQ(objectmap_lookup_ref(map, second.id), nullptr); EXPECT_EQ(objectmap_raw_lookup(map, 1), 0); EXPECT_NE(objectmap_lookup_ref(map, third.id), nullptr); EXPECT_NE(objectmap_raw_lookup(map, 2), 0); log_enable_stdout(false); objectmap_deallocate(map); log_enable_stdout(true); return 0; }