This is what I came up with:
The Application registers the Engine as subsystem and also removes it when the Engine is stoped.
I don’t know how to make this work on Android/iOS since I’m not targeting those platforms (Perhaps remove the Engine subsystem in RunFrame when exiting?), but here’s some code:
Application.cpp
Application::Application(Context *context) :
Object(context),
exitCode_(EXIT_SUCCESS)
{
...
engine_ = context_->RegisterSubsystem<Engine>();
...
}
int Application::Run()
{
...
Stop();
// Now this Application is the only object holding a reference to an Engine instance.
context_->RemoveSubsystem<Engine>();
return exitCode_;
...
}
Context.cpp
Context::~Context()
{
subsystems_.Clear();
factories_.Clear();
...
}
Engine.h
class URHO3D_API Engine : public Object
{
...
private:
SharedPtr<FileSystem> filesystem_;
#ifdef URHO3D_LOGGING
SharedPtr<Log> log_;
#endif
#ifdef URHO3D_PROFILING
SharedPtr<Profiler> profiler_;
SharedPtr<EventProfiler> eventProfiler_;
#endif
// Note the ordering, we want Graphics to be the last to be destructed.
SharedPtr<Graphics> graphics_;
SharedPtr<Renderer> renderer_;
SharedPtr<Input> input_;
SharedPtr<Audio> audio_;
SharedPtr<UI> ui_;
SharedPtr<Time> time_;
SharedPtr<WorkQueue> workQueue_;
SharedPtr<ResourceCache> resourceCache_;
SharedPtr<Localization> localization_;
#ifdef URHO3D_NETWORK
SharedPtr<Network> network_;
#endif
#ifdef URHO3D_DATABASE
SharedPtr<Database> database_;
#endif
...
}
Engine.cpp
Engine::Engine(Context *context) :
...
{
filesystem_ = context_->RegisterSubsystem<FileSystem>();
#ifdef URHO3D_LOGGING
log_ = context_->RegisterSubsystem<Log>();
#endif
#ifdef URHO3D_PROFILING
profiler_ = context_->RegisterSubsystem<Profiler>();
#endif
input_ = context_->RegisterSubsystem<Input>();
audio_ = context_->RegisterSubsystem<Audio>();
ui_ = context_->RegisterSubsystem<UI>();
time_ = context_->RegisterSubsystem<Time>();
workQueue_ = context_->RegisterSubsystem<WorkQueue>();
resourceCache_ = context_->RegisterSubsystem<ResourceCache>();
localization_ = context_->RegisterSubsystem<Localization>();
#ifdef URHO3D_NETWORK
network_ = context_->RegisterSubsystem<Network>();
#endif
#ifdef URHO3D_DATABASE
database_ = context_->RegisterSubsystem<Database>();
#endif
...
}
Engine::~Engine()
{
// Remove SDL based subsystems from the context.
context_->RemoveSubsystem<UI>();
context_->RemoveSubsystem<Audio>();
context_->RemoveSubsystem<Input>();
context_->RemoveSubsystem<Renderer>();
context_->RemoveSubsystem<Graphics>();
}
This also reduces the number of GetSubsystem() calls.