2013-07-02 63 views
0

我在設計實體組件系統的內存管理時遇到了一些問題,並且遇到了一些與設計細節有關的問題。這裏就是我試圖做(注意,所有這些類除外Entity實際上是虛擬的,所以會有很多不同的具體實現):內存管理設計

Program類將有Entity的容器。 Program將通過Entity循環並調用它們中的每一個更新。它也會有幾個SubSystem,它也會在每個循環中更新。

每個Entity將包含兩種類型的Component's。他們全部由內部的unique_ptr擁有,因爲他們的生命週期與實體直接相關。一種類型UpdateableComponent將在調用Entity.update()方法時更新。第二種SubSystemComponent將從其各自的SubSystem內更新。

現在,這是我的兩個問題。首先是一些Component將控制其父母Entity的生命週期。我目前的想法是Component將能夠調用一個函數parent.die()這將改變Entity內的內部標誌。然後,在Program完成循環更新後,它將循環第二次,並刪除在上次更新期間標記爲刪除的每個Entity。我不知道這是否是一種有效或者聰明的方式,儘管它應該避免Entity死亡的問題,而其Component仍在更新。

第二個問題是我不知道如何從SubSystem內引用SubSystemComponent's。由於它們是從Entity內部引用unique_ptr,所以我不能使用shared_ptrweak_ptr,並且當擁有組件的Entity死亡時,標準指針會結束晃動。我可以在Entity內切換爲shared_ptr,然後在SubSystem中使用weak_ptr,但我寧願不這樣做,因爲整個問題是Entity完全擁有它的Component's。

所以兩件事:

  • 可以將我的第一個想法可以以有意義的方式在改善?
  • 是否有實施weak_ptr排序的功能與unique_ptr一個簡單的方法,或者我應該切換到shared_ptr,只是確保不創建多個shared_ptrSubSystemComponent
+0

我想你可能想對內存管理做更多的研究,除非你在這個設計上死心塌地;循環遍歷整個分配的內存空間多次將不可擴展。智能指針始終是最初開始的一種很好且簡單的方法。此外,已經有一些建立完善的C++庫[垃圾收集](http://stackoverflow.com/questions/81062/garbage-collection-libraries-in-c)。 – Suedocode

+0

@Aggieboy我已經考慮過擴展問題,並且已經制定出只將部分數據加載到「實體」中,一次將我限制爲幾千個(可能最多10-20個)。如果我簡單地調用一個bool getter,並且可以從容器中刪除'Entity',那麼第二個循環真的會效率低下嗎?這種設計更重要的是提高代碼的可重用性而不是性能,並且我可以在以後輕鬆優化瓶頸。 –

+0

在嘗試更新組件之前,您可以簡單地檢查'hasToDie'標誌,這不是問題。然而,'unique_ptr'明確地被設計爲單一,嚴格的所有權。正如你已經指出的那樣,只要多於一個的對象需要一個引用(它保證總是有效的或者至少可檢查的),你就不會越過'shared_ptr'和可能的'weak_ptr'。 – arne

回答

1

燦我的第一個想法得到了有意義的改進?

很難說,不知道更多關於正在進行的工作的性質。例如,你沒有說過關於你使用線程的任何信息,但是看起來你的設計通過循環遍歷所有可能的更新來設置優先順序。對於一些低延遲很重要的事情,或者有一些理想的優先選擇,像這樣的循環序列並不好,而其他時候它是理想的。

還有其他的方法來協調從程序組件驅動的去除實體:

  • 返回代碼可能氣泡到循環過的實體,觸發來自實體的容器的擦除,
  • Observer模式或lambda/std::function可能允許程序指定清理行爲。

是否有實現的weak_ptr排序與功能的unique_ptr一個簡單的方法,

或者我應該只是切換到shared_ptr的,只是確保不創建多個子系統的shared_ptr組件

聽起來像合理的合適。您甚至可以將shared_ptr包裝在不可複製的類中以避免意外錯誤。

或者 - 如對上述實體的破壞 - 你可以使用事件,所以SubSystemComponent析構函數調用回到SubSystem協調SubSystemSubSystemComponent之間的聯繫。觀察者模式是實現這一目標的一種方式,爲lambda提供一個SubSystemComponent -side std::function更加靈活。無論哪種方式,Subsystem從其記錄中刪除SubSystemComponent