sidneytowers Posted March 25, 2025 Posted March 25, 2025 Hello! I'm trying to find a list of all engine events that are asynchronous to attach a function callback to. I had initially assumed that all events are called on the main thread, meaning that I would need to make my own thread in order to handle complex asynchronous tasks, but, going off the C++ Intersections example, it seems that tying function callbacks to getEventBeginRender() makes those function callbacks asynchronous (possibly on the render thread?). Is this a true understanding, or do I have something wrong? Also, if this is true, are there other event callbacks that are asynchronous but on their own separate threads, as to not bog down the event begin render callback thread? Best Regards and thank you for your time.
cash-metall Posted March 25, 2025 Posted March 25, 2025 Hello! in accordance with the article on the sequence of execution and where to put your code there are only two function witch would be invoked from another thread updateSync updateAsync but anyway this functions are frame-dependend, thats mean they should be finished at the end of the frame (in swap). Render callbacks will also be called from the main thread. 3 hours ago, sidneytowers said: meaning that I would need to make my own thread in order to handle complex asynchronous tasks yes, perhups it is best solution. you can see an example implementation of asynchronous tasks in cpp_component_samples/source/network/AsyncTasks.h(and .cpp). and sample about using in HttpImageRequestSample.cpp - The long task of requesting and downloading an image from the Internet is performed in a separate thread. In main thread you have a handle "promise-like", and check compleated in main thread. Also, the article about engine thread safety might be useful. 1
sidneytowers Posted March 25, 2025 Author Posted March 25, 2025 Understood, thank you. Having looked through the given pages, along with UnigineThread.h and AsyncTask.h, I have two related follow-up questions. 1. There does not seem to be any specifications for whether singletons or static functions are thread-safe to access and utilize, such as Engine::get() or World::getIntersection. Given that the intersection demo is still calling this functionality from the main thread, I worry about running into access issues or singleton duplication. Is this a just worry? 2. Are there no atomic functions for complex data types, such as floats? Is the only way to have such either to bit-cast a float into an integer of the same bit-depth, or to utilize the C++ standard library for atomics? Or are the atomic definitions within UnigineThread.h legacy functions and should be ignored? Apologies if these questions are answered in other documentation pages. It is difficult to find the time to read them all. Regardless, thank you for your time.
cash-metall Posted March 26, 2025 Posted March 26, 2025 You are welcome! 1. Engine::get returns pointer to engine instance. it does not create an instance of the class itself. so you need to create instance manualy, for example in main.cpp { // UnigineLogic AppSystemLogic system_logic; AppWorldLogic world_logic; AppEditorLogic editor_logic; // init engine Unigine::EnginePtr engine(argc, argv); // Unigine::Engine::get() return pointer to `engine` variable // enter main loop Unigine::Engine::get()->main(&system_logic, &world_logic, &editor_logic); engine->main(&system_logic, &world_logic, &editor_logic); // both line do the same return 0; } i.e. you initialize the singleton yourself other singletons such as World, Physics, Game are initialized together with the main Engine. So if you make engine initialization safe, all other singletons will be initialized safely as well. It is worth noting that the World::getIntersession functions are not completely thread-safe. You can only call them during init/syncupdate/update/postupdate/physicsupdate/swap. You cannot call intersession while the BSP tree is being rebuilt. 2. yes, you can use std::atomic conditionalVariables and std::threads. The main difference - Unigine::Mutex make more long spin before yeld thread. UnigineThread - just wrapper for OS threads (mostly designed for using in UnigineScript). 1
sidneytowers Posted March 26, 2025 Author Posted March 26, 2025 Thank you so much for your time and knowledge! Last clarification, is that limitation only true for World::getIntersection, or is it also true for physics, landscape (I know this one has an async intersection function, but regardless), and game intersections? Best regards and thank you again for your time!
cash-metall Posted March 27, 2025 Posted March 27, 2025 Yes, it is true for all types of intersection. Each system has own BSP tree (sometimes even several tree). And if we call intersection during rebuild this tree we will get crashes. This is also true if you modify the world yourself and in another thread call intersection. There are practically no locks in the engine - to get more perfomance, so you need to control access by yourself. 1
Recommended Posts