SanderMertens / flecs

A fast entity component system (ECS) for C & C++
https://www.flecs.dev
Other
6.47k stars 454 forks source link

_::type_name<T>() is not thread-safe, that will cause memory error! #1022

Closed Esp9527 closed 1 year ago

Esp9527 commented 1 year ago

Describe the bug _::type_name() is not thread-safe, that will cause memory error!

To Reproduce

`

#include "flecs.h"
#include <thread>
#include <map>

namespace component {
    struct Data {
        int i = 0;
    };
}
int main() {

    std::vector<std::shared_ptr<std::thread>>
        threads;

    for(int i = 0; i<10; i++) {
        threads.push_back(std::make_shared<std::thread>([](){
            while(true) {
                flecs::world world;
                world.component<component::Data>();
                world.component<std::map<uint64_t, component::Data>>();
            }
        }));
    }

    for(auto& t : threads)
        t->join();

    return 0;
}

` this will crash!

Follow a simple solution

` // modifier _::type_name()

template <typename T>
inline static const char* type_name() {
    static const size_t len = ECS_FUNC_TYPE_LEN(const char*, type_name, ECS_FUNC_NAME);
    static char result[len + 1] = {};
    static const size_t front_len = ECS_FUNC_NAME_FRONT(const char*, type_name);
    // old code:    return ecs_cpp_get_type_name(result, ECS_FUNC_NAME, len, front_len);
    static char* out = ecs_cpp_get_type_name(result, ECS_FUNC_NAME, len, front_len);
    return out;
} 

` other function maybe also need, symbol_name() , enum_constant_to_name<E, E C> ...

SanderMertens commented 1 year ago

That's correct, but the entire Flecs API is not thread safe :)

Anything that mutates the world should either happen when you have exclusive access to the world (e.g. component registration should happen on the main thread) or should be enqueued as command (e.g. ECS operations like add, remove, set, get_mut, etc).