diff --git a/Source/Foundation/bsfUtility/Utility/BsEvent.h b/Source/Foundation/bsfUtility/Utility/BsEvent.h index 8bb57379c..6959a1cad 100644 --- a/Source/Foundation/bsfUtility/Utility/BsEvent.h +++ b/Source/Foundation/bsfUtility/Utility/BsEvent.h @@ -124,7 +124,7 @@ namespace bs } /** - * Called when the event handle no longer keeps a reference to the connection data. This means we might be able to + * Called when the event handle no longer keeps a reference to the connection data. This means we might be able to * free (and reuse) its memory if the event is done with it too. */ void freeHandle(BaseConnectionData* conn) @@ -220,8 +220,8 @@ namespace bs /** * Allows direct conversion of a handle to bool. * - * @note - * Additional struct is needed because we can't directly convert to bool since then we can assign pointer to bool + * @note + * Additional struct is needed because we can't directly convert to bool since then we can assign pointer to bool * and that's wrong. */ operator int Bool_struct::*() const @@ -243,7 +243,7 @@ namespace bs private: BaseConnectionData* mConnection = nullptr; SPtr mEventData; - }; + }; /** @} */ @@ -260,7 +260,7 @@ namespace bs * * @note Callback method return value is ignored. */ - // Note: I could create a policy template argument that allows creation of + // Note: I could create a policy template argument that allows creation of // lockable and non-lockable events in the case mutex is causing too much overhead. template class TEvent diff --git a/Source/Foundation/bsfUtility/Utility/BsMessageHandler.cpp b/Source/Foundation/bsfUtility/Utility/BsMessageHandler.cpp index c5781683f..7cacd5955 100644 --- a/Source/Foundation/bsfUtility/Utility/BsMessageHandler.cpp +++ b/Source/Foundation/bsfUtility/Utility/BsMessageHandler.cpp @@ -45,7 +45,7 @@ namespace bs HMessage MessageHandler::listen(MessageId message, std::function callback) { UINT32 callbackId = mNextCallbackId++; - + MessageHandlerData data; data.id = callbackId; data.callback = callback; @@ -66,7 +66,7 @@ namespace bs Vector& handlerData = iterFind->second; handlerData.erase( - std::remove_if(handlerData.begin(), handlerData.end(), + std::remove_if(handlerData.begin(), handlerData.end(), [&](MessageHandlerData& x) { return x.id == handleId; diff --git a/Source/Foundation/bsfUtility/Utility/BsModule.h b/Source/Foundation/bsfUtility/Utility/BsModule.h index 307d9b7b2..11dc29afa 100644 --- a/Source/Foundation/bsfUtility/Utility/BsModule.h +++ b/Source/Foundation/bsfUtility/Utility/BsModule.h @@ -12,7 +12,7 @@ namespace bs */ /** - * Represents one engine module. Essentially it is a specialized type of singleton. Module must be manually started up + * Represents one engine module. Essentially it is a specialized type of singleton. Module must be manually started up * and shut down before and after use. */ template @@ -27,13 +27,13 @@ namespace bs { if (!isStartedUp()) { - BS_EXCEPT(InternalErrorException, + BS_EXCEPT(InternalErrorException, "Trying to access a module but it hasn't been started up yet."); } if (isDestroyed()) { - BS_EXCEPT(InternalErrorException, + BS_EXCEPT(InternalErrorException, "Trying to access a destroyed module."); } @@ -41,41 +41,45 @@ namespace bs } /** - * Returns a pointer to the module instance. Module has to have been started up first otherwise an exception will + * Returns a pointer to the module instance. Module has to have been started up first otherwise an exception will * be thrown. */ static T* instancePtr() { if (!isStartedUp()) { - BS_EXCEPT(InternalErrorException, + BS_EXCEPT(InternalErrorException, "Trying to access a module but it hasn't been started up yet."); } if (isDestroyed()) { - BS_EXCEPT(InternalErrorException, + BS_EXCEPT(InternalErrorException, "Trying to access a destroyed module."); } return _instance(); } - + /** Constructs and starts the module using the specified parameters. */ template static void startUp(Args &&...args) { if (isStartedUp()) BS_EXCEPT(InternalErrorException, "Trying to start an already started module."); + T * test = nullptr; + bool success = _instance().compare_exchange_strong(test, bs_new(std::forward(args)...)); + + if (!success) + BS_EXCEPT(InternalErrorException, "Race condition when starting module."); - _instance() = bs_new(std::forward(args)...); isStartedUp() = true; ((Module*)_instance())->onStartUp(); } /** - * Constructs and starts a specialized type of the module. Provided type must derive from type the Module is + * Constructs and starts a specialized type of the module. Provided type must derive from type the Module is * initialized with. */ template @@ -97,19 +101,19 @@ namespace bs { if (isDestroyed()) { - BS_EXCEPT(InternalErrorException, + BS_EXCEPT(InternalErrorException, "Trying to shut down an already shut down module."); } - - if (!isStartedUp()) + + if (!isStartedUp()) { - BS_EXCEPT(InternalErrorException, + BS_EXCEPT(InternalErrorException, "Trying to shut down a module which was never started."); } ((Module*)_instance())->onShutDown(); - bs_delete(_instance()); + bs_delete(_instance().load()); isDestroyed() = true; } @@ -131,42 +135,42 @@ namespace bs /** * Override if you want your module to be notified once it has been constructed and started. - * - * @note Useful when your module is polymorphic and you cannot perform some implementation specific + * + * @note Useful when your module is polymorphic and you cannot perform some implementation specific * initialization in constructor itself. */ virtual void onStartUp() {} /** * Override if you want your module to be notified just before it is deleted. - * - * @note Useful when your module is polymorphic and you might want to perform some kind of clean up perhaps + * + * @note Useful when your module is polymorphic and you might want to perform some kind of clean up perhaps * overriding that of a base class. */ virtual void onShutDown() {} /** Returns a singleton instance of this module. */ - static T*& _instance() + static std::atomic& _instance() { - static T* inst = nullptr; + static std::atomic inst{nullptr}; return inst; } /** * Checks has the Module been shut down. - * + * * @note If module was never even started, this will return false. */ - static bool& isDestroyed() + static std::atomic& isDestroyed() { - static bool inst = false; + static std::atomic inst{false}; return inst; } /** Checks has the Module been started up. */ - static bool& isStartedUp() + static std::atomic& isStartedUp() { - static bool inst = false; + static std::atomic inst{false}; return inst; } }; diff --git a/Source/Foundation/bsfUtility/Utility/BsPlatformUtility.h b/Source/Foundation/bsfUtility/Utility/BsPlatformUtility.h index 4be8caaec..4cd376720 100644 --- a/Source/Foundation/bsfUtility/Utility/BsPlatformUtility.h +++ b/Source/Foundation/bsfUtility/Utility/BsPlatformUtility.h @@ -42,7 +42,7 @@ namespace bs public: /** * Terminates the current process. - * + * * @param[in] force True if the process should be forcefully terminated with no cleanup. */ static void terminate(bool force = false); @@ -57,7 +57,7 @@ namespace bs * @{ */ - /** + /** * Assigns information about GPU hardware. This data will be returned by getSystemInfo() when requested. This is * expeced to be called by the render API backend when initialized. */