Godric Seer
Godric Seer

Reputation: 379

Memory Management Design

I am having some issues designing the memory management for an Entity-Component system and am having some issues coming up with the detail of the design. Here is what I am trying to do (note that all of these classes except Entity are actually virtual, so will have many different specific implementations):

The Program class will have a container of Entity's. The Program will loop through the Entity's and call update on each of them. It will also have a few SubSystem's, which it will also update on each loop through.

Each Entity will contain two types of Component's. All of them will be owned by a unique_ptr inside the Entity since their lifetime is directly tied to the entity. One type, UpdateableComponent, will be updated when the Entity.update() method is called. The second type SubSystemComponent will be updated from within their respective SubSystem.

Now here are my two problems. The first is that some of the Component's will control the lifetime of their parent Entity. My current idea for this is that Component will be able to call a function parent.die() which would change an internal flag inside Entity. Then after Program finishes looping through its updates, it loops through a second time and removes each Entity which was marked for deletion during the last update. I don't know if this is an efficient or smart way to go about it, although it should avoid the problem of an Entity dieing while its Component's are still updating.

The second issue is that I am not sure how to reference SubSystemComponent's from within SubSystem. Since they are refered to by a unique_ptr from inside Entity, I can't use a shared_ptr or a weak_ptr, and a standard pointer would end up dangling when the Entity owning a component dies. I could switch to a shared_ptr inside the Entity for these, then use a weak_ptr in the SubSystem's, however I would prefer to not do this because the whole point is that Entity completely owns its Component's.

So 2 things:

Upvotes: 0

Views: 239

Answers (1)

Tony Delroy
Tony Delroy

Reputation: 106096

Can my first idea be improved upon in a meaningful way?

Hard to say without knowing more about the nature of the work being undertaken. For example, you haven't said anything about your use of threads, but it seems your design gives equal priority to all the possible updates by cycling through things in a set sequence. For some things where low latency is important, or there's some useful prioritorisation that would ideally be done, a looping sequence like that isn't good, while other times it's ideal.

There are other ways to coordinate the Component-driven removal of Entities from the Program:

  • return codes could bubble up to the loop over entities, triggering an erase from the container of Entities,
  • an Observer pattern or lambda/std::function could allow the Program to specify cleanup behaviour.

Is there an easy way to implement a weak_ptr sort of functionality with unique_ptr,

No.

or should I just switch to shared_ptr and just make sure to not create more than one shared_ptr to the SubSystemComponent's

It sounds like a reasonable fit. You could even wrap a shared_ptr in a non-copyable class to avoid accidental mistakes.

Alternatively - as for Entity destruction above - you could coordinate the linkage between SubSystem and SubSystemComponent using events, so the SubSystemComponent destructor calls back to the SubSystem. An Observer pattern is one way to do this, a SubSystemComponent-side std::function fed a lambda is even more flexible. Either way, the Subsystem removes the SubSystemComponent from its records.

Upvotes: 1

Related Questions