// Copyright Epic Games, Inc. All Rights Reserved. #include "CoreMinimal.h" #include "HAL/PlatformProcess.h" #include "Misc/CoreMisc.h" #include "Misc/CoreDelegates.h" #include "Modules/ModuleManager.h" #include "Bus/MessageDispatchTask.h" #include "IMessageBus.h" #include "Bus/MessageBus.h" #include "Bridge/MessageBridge.h" #include "IMessagingModule.h" #include "INetworkMessagingExtension.h" #ifndef PLATFORM_SUPPORTS_MESSAGEBUS #define PLATFORM_SUPPORTS_MESSAGEBUS !(WITH_SERVER_CODE && UE_BUILD_SHIPPING) #endif DEFINE_LOG_CATEGORY(LogMessaging); /** * Implements the Messaging module. */ class FMessagingModule : public FSelfRegisteringExec , public IMessagingModule { protected: //~ FSelfRegisteringExec interface virtual bool Exec_Runtime(UWorld* InWorld, const TCHAR* Cmd, FOutputDevice& Ar) override { if (!FParse::Command(&Cmd, TEXT("MESSAGING"))) { return false; } if (FParse::Command(&Cmd, TEXT("STATUS"))) { if (DefaultBus.IsValid()) { Ar.Log(TEXT("Default message bus has been initialized.")); } else { Ar.Log(TEXT("Default message bus has NOT been initialized yet.")); } } else { // show usage Ar.Log(TEXT("Usage: MESSAGING ")); Ar.Log(TEXT("")); Ar.Log(TEXT("Command")); Ar.Log(TEXT(" STATUS = Displays the status of the default message bus")); } return true; } public: //~ IMessagingModule interface virtual FOnMessageBusStartupOrShutdown& OnMessageBusStartup() override { return OnMessageBusStartupDelegate; } virtual FOnMessageBusStartupOrShutdown& OnMessageBusShutdown() override { return OnMessageBusShutdownDelegate; } virtual TSharedPtr CreateBridge(const FMessageAddress& Address, const TSharedRef& Bus, const TSharedRef& Transport) override { return MakeShared(Address, Bus, Transport); } virtual TSharedPtr CreateBus(const TSharedPtr& RecipientAuthorizer) override { return CreateBus(FGuid::NewGuid().ToString(), RecipientAuthorizer); } virtual TSharedPtr CreateBus(FString InName, const TSharedPtr& RecipientAuthorizer) override { TSharedRef Bus = MakeShared(MoveTemp(InName), RecipientAuthorizer); Bus->OnShutdown().AddLambda([this, WeakBus = TWeakPtr(Bus)]() { WeakBuses.RemoveSwap(WeakBus); OnMessageBusShutdownDelegate.Broadcast(WeakBus); }); WeakBuses.Add(Bus); OnMessageBusStartupDelegate.Broadcast(Bus); return Bus; } virtual TSharedPtr GetDefaultBus() const override { return DefaultBus; } virtual TArray> GetAllBuses() const override { TArray> Buses; for (const TWeakPtr& WeakBus : WeakBuses) { if (TSharedPtr Bus = WeakBus.Pin()) { Buses.Add(Bus.ToSharedRef()); } } return Buses; } public: //~ IModuleInterface interface virtual void StartupModule() override { #if PLATFORM_SUPPORTS_MESSAGEBUS FCoreDelegates::OnPreExit.AddRaw(this, &FMessagingModule::HandleCorePreExit); DefaultBus = CreateBus(TEXT("DefaultBus"), nullptr); #endif //PLATFORM_SUPPORTS_MESSAGEBUS } virtual void ShutdownModule() override { ShutdownDefaultBus(); #if PLATFORM_SUPPORTS_MESSAGEBUS FCoreDelegates::OnPreExit.RemoveAll(this); #endif //PLATFORM_SUPPORTS_MESSAGEBUS } virtual bool SupportsDynamicReloading() override { return false; } protected: void ShutdownDefaultBus() { if (!DefaultBus.IsValid()) { return; } TWeakPtr DefaultBusPtr = DefaultBus; DefaultBus->Shutdown(); DefaultBus.Reset(); // wait for the bus to shut down int32 SleepCount = 0; while (DefaultBusPtr.IsValid()) { if (SleepCount > 10) { check(!"Something is holding on the default message bus"); break; } ++SleepCount; FPlatformProcess::Sleep(0.1f); } // validate all other buses were also properly shutdown for (TWeakPtr WeakBus : WeakBuses) { if (WeakBus.IsValid()) { check(!"Something is holding on a message bus"); break; } } } private: /** Callback for Core shutdown. */ void HandleCorePreExit() { ShutdownDefaultBus(); } private: /** Holds the message bus. */ TSharedPtr DefaultBus; /** All buses that were created through this module including the default one. */ TArray> WeakBuses; /** The delegate fired when a message bus instance is started. */ FOnMessageBusStartupOrShutdown OnMessageBusStartupDelegate; /** The delegate fired when a message bus instance is shutdown. */ FOnMessageBusStartupOrShutdown OnMessageBusShutdownDelegate; }; FName INetworkMessagingExtension::ModularFeatureName("NetworkMessaging"); IMPLEMENT_MODULE(FMessagingModule, Messaging);