From 28895baa88d083994a817f27a91a07f9f308a7c3 Mon Sep 17 00:00:00 2001 From: Anton Tarasenko Date: Sun, 17 Jul 2022 02:30:19 +0700 Subject: [PATCH] Refactor shutting down process --- .../AcediaEnvironment/AcediaEnvironment.uc | 88 ++++++++++++++++--- sources/BaseRealm/Global.uc | 1 + .../ServerRealm/API/Unreal/ServerUnrealAPI.uc | 16 ++++ 3 files changed, 92 insertions(+), 13 deletions(-) diff --git a/sources/BaseRealm/AcediaEnvironment/AcediaEnvironment.uc b/sources/BaseRealm/AcediaEnvironment/AcediaEnvironment.uc index 0067cc9..4a0269b 100644 --- a/sources/BaseRealm/AcediaEnvironment/AcediaEnvironment.uc +++ b/sources/BaseRealm/AcediaEnvironment/AcediaEnvironment.uc @@ -44,6 +44,8 @@ class AcediaEnvironment extends AcediaObject; * considered enabled at the same time. */ +var private bool acediaShutDown; + var private array< class<_manifest> > availablePackages; var private array< class<_manifest> > loadedPackages; @@ -58,9 +60,62 @@ var private LoggerAPI.Definition errNotRegistered, errFeatureAlreadyEnabled; var private LoggerAPI.Definition warnFeatureAlreadyEnabled; var private LoggerAPI.Definition errFeatureClassAlreadyEnabled; +var private SimpleSignal onShutdownSignal; +var private SimpleSignal onShutdownSystemSignal; var private Environment_FeatureEnabled_Signal onFeatureEnabledSignal; var private Environment_FeatureDisabled_Signal onFeatureDisabledSignal; +protected function Constructor() +{ + // Always register our core package + RegisterPackage_S("AcediaCore"); + onShutdownSignal = SimpleSignal( + _.memory.Allocate(class'SimpleSignal')); + onShutdownSystemSignal = SimpleSignal( + _.memory.Allocate(class'SimpleSignal')); + onFeatureEnabledSignal = Environment_FeatureEnabled_Signal( + _.memory.Allocate(class'Environment_FeatureEnabled_Signal')); + onFeatureDisabledSignal = Environment_FeatureDisabled_Signal( + _.memory.Allocate(class'Environment_FeatureDisabled_Signal')); +} + +protected function Finalizer() +{ + _.memory.Free(onShutdownSignal); + _.memory.Free(onShutdownSystemSignal); + _.memory.Free(onFeatureEnabledSignal); + _.memory.Free(onFeatureDisabledSignal); +} + +/** + * Signal that will be emitted before Acedia shuts down. + * At this point all APIs should still exist and function. + * + * [Signature] + * void () + */ +/* SIGNAL */ +public final function SimpleSlot OnShutDown(AcediaObject receiver) +{ + return SimpleSlot(onShutdownSignal.NewSlot(receiver)); +} + +/** + * Signal that will be emitted during Acedia shut down. System API use it to + * clean up after themselves, so one shouldn't rely on them. + * + * There is no reason to use this signal unless you're reimplementing one of + * the APIs. Otherwise you probably want to use `OnShutDown()` signal instead. + * + * [Signature] + * void () + */ +/* SIGNAL */ +public final function SimpleSlot OnShutDownSystem(AcediaObject receiver) +{ + return SimpleSlot(onShutdownSystemSignal.NewSlot(receiver)); +} + /** * Signal that will be emitted when new `Feature` is enabled. * Emitted after `Feature`'s `OnEnabled()` method was called. @@ -96,20 +151,27 @@ public final function Environment_FeatureDisabled_Slot OnFeatureDisabled( onFeatureEnabledSignal.NewSlot(receiver)); } -protected function Constructor() -{ - // Always register our core package - RegisterPackage_S("AcediaCore"); - onFeatureEnabledSignal = Environment_FeatureEnabled_Signal( - _.memory.Allocate(class'Environment_FeatureEnabled_Signal')); - onFeatureDisabledSignal = Environment_FeatureDisabled_Signal( - _.memory.Allocate(class'Environment_FeatureDisabled_Signal')); -} - -protected function Finalizer() +/** + * Shuts AcediaCore down, performing all the necessary cleaning up. + */ +public final function Shutdown() { - _.memory.Free(onFeatureEnabledSignal); - _.memory.Free(onFeatureDisabledSignal); + local LevelCore core; + if (acediaShutDown) { + return; + } + DisableAllFeatures(); + onShutdownSignal.Emit(); + onShutdownSystemSignal.Emit(); + core = class'ServerLevelCore'.static.GetInstance(); + if (core != none) { + core.Destroy(); + } + core = class'ClientLevelCore'.static.GetInstance(); + if (core != none) { + core.Destroy(); + } + acediaShutDown = true; } /** diff --git a/sources/BaseRealm/Global.uc b/sources/BaseRealm/Global.uc index e22e4c6..26b5e5b 100644 --- a/sources/BaseRealm/Global.uc +++ b/sources/BaseRealm/Global.uc @@ -59,6 +59,7 @@ protected function Initialize() // Special case that we cannot spawn with memory API since it obviously // does not exist yet! memory = new class'MemoryAPI'; + memory._constructor(); // `TextAPI` and `CollectionsAPI` need to be loaded before `LoggerAPI` ref = RefAPI(memory.Allocate(class'RefAPI')); box = BoxAPI(memory.Allocate(class'BoxAPI')); diff --git a/sources/ServerRealm/API/Unreal/ServerUnrealAPI.uc b/sources/ServerRealm/API/Unreal/ServerUnrealAPI.uc index 61bf0c2..2fb8889 100644 --- a/sources/ServerRealm/API/Unreal/ServerUnrealAPI.uc +++ b/sources/ServerRealm/API/Unreal/ServerUnrealAPI.uc @@ -21,6 +21,22 @@ class ServerUnrealAPI extends ServerUnrealAPIBase; var private LoggerAPI.Definition fatalNoStalker; +protected function Constructor() +{ + _.environment.OnShutDownSystem(self).connect = HandleShutdown; +} + +protected function HandleShutdown() +{ + local UnrealService service; + + service = UnrealService(class'UnrealService'.static.GetInstance()); + // This has to clean up anything we've added + if (service != none) { + service.Destroy(); + } +} + /* SIGNAL */ public function Unreal_OnTick_Slot OnTick( AcediaObject receiver)