Skip to content

Commit afb504f

Browse files
committed
Disallow system create after manager init
* Also add tickIndex counter.
1 parent e9d2aa8 commit afb504f

5 files changed

Lines changed: 47 additions & 168 deletions

File tree

README.md

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,6 @@ class PhysicsSystem final : public ComponentSystem<RigidBodyComponent, false>
3939
auto manager = Manager::Instance::get();
4040
ECSM_SUBSCRIBE_TO_EVENT("Update", PhysicsSystem::update);
4141
}
42-
~PhysicsSystem() final
43-
{
44-
if (Manager::get()->isRunning)
45-
{
46-
auto manager = Manager::Instance::get();
47-
ECSM_UNSUBSCRIBE_FROM_EVENT("Update", PhysicsSystem::update);
48-
}
49-
}
5042

5143
void update()
5244
{
@@ -62,7 +54,7 @@ class PhysicsSystem final : public ComponentSystem<RigidBodyComponent, false>
6254
friend class ecsm::Manager;
6355
};
6456

65-
void ecsmExample()
57+
void entryPoint()
6658
{
6759
auto manager = new ecsm::Manager();
6860
manager->createSystem<PhysicsSystem>();
@@ -75,8 +67,8 @@ void ecsmExample()
7567
auto rigidBodyView = manager->add<RigidBodyComponent>(rigidBody);
7668
rigidBodyView->size = 1.0f;
7769

78-
manager->start();
79-
70+
manager->enterLoop();
71+
manager->terminate();
8072
delete manager;
8173
}
8274
```

include/ecsm.hpp

Lines changed: 20 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@ class Manager final : public Singleton<Manager, false>
354354
OrderedEvents orderedEvents;
355355
GarbageComponents garbageComponents;
356356
std::mutex locker;
357+
uint64_t tickIndex = 0;
357358
bool initialized = false;
358359

359360
#ifndef NDEBUG
@@ -364,7 +365,7 @@ class Manager final : public Singleton<Manager, false>
364365
public:
365366
volatile bool isRunning = false; /**< Is manager update loop running. */
366367

367-
/**
368+
/*******************************************************************************************************************
368369
* @brief Creates a new manager instance.
369370
* @param setSingleton set manager singleton instance
370371
*/
@@ -374,11 +375,11 @@ class Manager final : public Singleton<Manager, false>
374375
*/
375376
~Manager();
376377

377-
/*******************************************************************************************************************
378+
/**
378379
* @brief Creates a new system instance.
379380
*
380381
* @details
381-
* Instantiates a new system and registers it component,
382+
* Allocates a new system instance and registers it component,
382383
* but initialization occurs only after the @ref initialize() call.
383384
*
384385
* @tparam T target system type
@@ -391,6 +392,8 @@ class Manager final : public Singleton<Manager, false>
391392
void createSystem(Args&&... args)
392393
{
393394
static_assert(std::is_base_of_v<System, T>, "Must be derived from the System class.");
395+
if (initialized)
396+
throw EcsmError("Manager is already initialized, can't create a new system.");
394397
#ifndef NDEBUG
395398
if (isChanging)
396399
throw EcsmError("Creation of the system inside other create/destroy is not allowed.");
@@ -405,42 +408,6 @@ class Manager final : public Singleton<Manager, false>
405408
#endif
406409
}
407410

408-
/**
409-
* @brief Terminates and destroys system.
410-
* @param type target system typeid()
411-
* @throw EcsmError if system is not found.
412-
*/
413-
void destroySystem(std::type_index type);
414-
/**
415-
* @brief Terminates and destroys system.
416-
* @tparam T target system type
417-
* @throw EcsmError if system is not found.
418-
*/
419-
template<class T>
420-
void destroySystem()
421-
{
422-
static_assert(std::is_base_of_v<System, T>, "Must be derived from the System class.");
423-
destroySystem(typeid(T));
424-
}
425-
426-
/**
427-
* @brief Terminates and destroys system if exists.
428-
* @param type target system typeid()
429-
* @return True if system is destroyed, otherwise false.
430-
*/
431-
bool tryDestroySystem(std::type_index type);
432-
/**
433-
* @brief Terminates and destroys system if exists.
434-
* @tparam T target system type
435-
* @return True if system is destroyed, otherwise false.
436-
*/
437-
template<class T>
438-
bool tryDestroySystem()
439-
{
440-
static_assert(std::is_base_of_v<System, T>, "Must be derived from the System class.");
441-
return tryDestroySystem(typeid(T));
442-
}
443-
444411
/*******************************************************************************************************************
445412
* @brief Adds specified system to the system group.
446413
*
@@ -1323,28 +1290,37 @@ class Manager final : public Singleton<Manager, false>
13231290
* @note Use manager functions to check if component is garbage.
13241291
*/
13251292
const GarbageComponents& getGarbageComponents() const noexcept { return garbageComponents; }
1293+
/**
1294+
* @brief Returns current tick index since manager creation. (Total update count)
1295+
*/
1296+
uint64_t getTickIndex() const noexcept { return tickIndex; }
13261297
/**
13271298
* @brief Returns true if manager is initialized.
1299+
* @note You can't add more systems after manager initialization.
13281300
*/
13291301
bool isInitialized() const noexcept { return initialized; }
13301302

13311303
/*******************************************************************************************************************
1332-
* @brief Initializes all created systems.
1304+
* @brief Initializes all manager created systems.
13331305
* @throw EcsmError if manager is already initialized.
13341306
*/
13351307
void initialize();
1308+
/**
1309+
* @brief Terminates all manager created systems.
1310+
* @throw EcsmError if manager is already terminated.
1311+
*/
1312+
void terminate();
13361313

13371314
/**
1338-
* @brief Runs ordered events and disposes destroyed resources on each tick.
1315+
* @brief Runs ordered events and disposes destroyed resources.
13391316
* @throw EcsmError if manager is not initialized.
13401317
*/
13411318
void update();
1342-
13431319
/**
1344-
* @brief Enters update loop. Executes @ref update() on each tick.
1320+
* @brief Enters update loop. Executes @ref Manager::update() on each tick.
13451321
* @throw EcsmError if manager is not initialized.
13461322
*/
1347-
void start();
1323+
void enterLoop();
13481324

13491325
/*******************************************************************************************************************
13501326
* @brief Actually destroys garbage components.

include/singleton.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,15 @@ class Singleton
5858
if (set)
5959
setSingleton();
6060
}
61+
/**
62+
* @brief Destroys singleton class instance.
63+
* @note It also unsets singleton if it's the same as this system.
64+
*/
65+
virtual ~Singleton()
66+
{
67+
if (this == singletonInstance)
68+
unsetSingleton();
69+
}
6170

6271
/**
6372
* @brief Sets a new class singleton instance.

source/ecsm.cpp

Lines changed: 12 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,6 @@ Manager::Manager(bool setSingleton) : Singleton(setSingleton)
7676
}
7777
Manager::~Manager()
7878
{
79-
if (initialized)
80-
{
81-
runEvent("PreDeinit");
82-
runEvent("Deinit");
83-
runEvent("PostDeinit");
84-
}
85-
8679
entities.clear(false);
8780

8881
#ifndef NDEBUG
@@ -128,93 +121,6 @@ void Manager::addSystem(System* system, std::type_index type)
128121

129122
if (!systems.emplace(type, system).second)
130123
throw EcsmError("System is already created. (name: " + typeToString(type) + ")");
131-
132-
if (isRunning)
133-
{
134-
runEvent("PreInit");
135-
runEvent("Init");
136-
runEvent("PostInit");
137-
}
138-
}
139-
140-
//**********************************************************************************************************************
141-
void Manager::destroySystem(std::type_index type)
142-
{
143-
#ifndef NDEBUG
144-
if (isChanging)
145-
throw EcsmError("Destruction of the system inside other create/destroy is not allowed.");
146-
isChanging = true;
147-
#endif
148-
149-
auto searchResult = systems.find(type);
150-
if (searchResult == systems.end())
151-
throw EcsmError("System is not created. (type: " + typeToString(type) + ")");
152-
153-
if (isRunning)
154-
{
155-
runEvent("PreDeinit");
156-
runEvent("Deinit");
157-
runEvent("PostDeinit");
158-
}
159-
160-
auto system = searchResult->second;
161-
systems.erase(searchResult);
162-
163-
auto componentName = system->getComponentName();
164-
if (!componentName.empty())
165-
{
166-
auto eraseResult = componentNames.erase(componentName);
167-
if (eraseResult != 1)
168-
{
169-
throw EcsmError("Failed to erase system component name. ("
170-
"componentName: " + std::string(componentName) + ", "
171-
"systemType: " + typeToString(type) + ")");
172-
}
173-
}
174-
175-
auto componentType = system->getComponentType();
176-
if (componentType != typeid(Component))
177-
{
178-
auto eraseResult = componentTypes.erase(componentType);
179-
if (eraseResult != 1)
180-
{
181-
throw EcsmError("Failed to erase system component type. ("
182-
"componentType: " + typeToString(componentType) + ", "
183-
"systemType: " + typeToString(type) + ")");
184-
}
185-
}
186-
187-
delete system;
188-
189-
#ifndef NDEBUG
190-
isChanging = false;
191-
#endif
192-
}
193-
bool Manager::tryDestroySystem(std::type_index type)
194-
{
195-
#ifndef NDEBUG
196-
if (isChanging)
197-
throw EcsmError("Destruction of the system inside other create/destroy is not allowed.");
198-
isChanging = true;
199-
#endif
200-
201-
auto result = systems.find(type);
202-
if (result != systems.end())
203-
{
204-
#ifndef NDEBUG
205-
isChanging = false;
206-
#endif
207-
return false;
208-
}
209-
210-
auto system = result->second;
211-
systems.erase(result);
212-
delete system;
213-
214-
#ifndef NDEBUG
215-
isChanging = false;
216-
#endif
217-
return true;
218124
}
219125

220126
//**********************************************************************************************************************
@@ -664,6 +570,16 @@ void Manager::initialize()
664570
runEvent("PostInit");
665571
initialized = true;
666572
}
573+
void Manager::terminate()
574+
{
575+
if (!initialized)
576+
throw EcsmError("Manager is already terminated.");
577+
578+
runEvent("PreDeinit");
579+
runEvent("Deinit");
580+
runEvent("PostDeinit");
581+
initialized = false;
582+
}
667583

668584
void Manager::update()
669585
{
@@ -675,15 +591,15 @@ void Manager::update()
675591
disposeGarbageComponents();
676592
disposeEntities();
677593
disposeSystemComponents();
594+
tickIndex++;
678595
locker.unlock();
679596
}
680-
void Manager::start()
597+
void Manager::enterLoop()
681598
{
682599
if (!initialized)
683600
throw EcsmError("Manager is not initialized.");
684601

685602
isRunning = true;
686-
687603
while (isRunning)
688604
update();
689605
}

tests/test-ecsm.cpp

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,6 @@ class TestSystem final : public ComponentSystem<TestComponent>, public Singleton
4040
ECSM_SUBSCRIBE_TO_EVENT("Update", TestSystem::update);
4141
ECSM_SUBSCRIBE_TO_EVENT("PostUpdate", TestSystem::postUpdate);
4242
}
43-
~TestSystem() override
44-
{
45-
if (Manager::Instance::get()->isRunning)
46-
{
47-
auto manager = Manager::Instance::get();
48-
ECSM_UNSUBSCRIBE_FROM_EVENT("Init", TestSystem::init);
49-
ECSM_UNSUBSCRIBE_FROM_EVENT("Update", TestSystem::update);
50-
ECSM_UNSUBSCRIBE_FROM_EVENT("PostUpdate", TestSystem::postUpdate);
51-
}
52-
53-
unsetSingleton();
54-
}
5543

5644
void copyComponent(View<Component> source, View<Component> destination) override
5745
{
@@ -186,12 +174,10 @@ static void testCommonFlow()
186174
if (componentMemory->ID != 0) // WARNING! You should't do this, it's just safety check!
187175
throw runtime_error("Bad test component data after dispose.");
188176

189-
manager->destroySystem<TestSystem>();
190-
191-
if (manager->has<TestSystem>())
192-
throw runtime_error("Test system is not destroyed.");
193-
194177
manager->unregisterEvent("PostUpdate");
178+
if (manager->hasEvent("PostUpdate"))
179+
throw runtime_error("PostUpdate not unregistered.");
180+
195181
delete manager;
196182
}
197183

0 commit comments

Comments
 (0)