[C++] Help me choose container

Started by
5 comments, last by ccsdu2004 13 years, 5 months ago
I am continuing "pursuit" to solve my problem that i have started here.

Here is what am i doing and what i need:

I am trying to create scene manager class and manage resources that it holds.
I need some type of container that can hold just pointers to data/resources that does not
allocate/deallocate nothing since i am doing it by hand. Here is some half pseudo (inserting into container):
LightSceneElement* SceneManager::AddLightSceneElement(SceneElement* parent, ELightType type){	LightSceneElement* pLight = new LightSceneElement();	pLight->Init(this, parent, type);// intit basic properties	conatainerLights.insert(pLight);// this should be my imagenary container	return pLight;// return pLight so i can take control elswhere and manipulate it}


then when finished delete all data:
void SceneManager::Close(){    ...    foreach element in containerLights    {        LightSceneElement* pLight = *containerLights.iter;//obtain pointer        delete pLight; //delete data that it points to        pLight = 0;    }}


It should have fast function to sort my elements (that i have talked about in linked thread)
and it should be fast at inserting elements:

void SceneManager::Draw(){    ...    // for example render static meshes    container<SceneElement*> containerNotCulledStaticMeshes;// name shoud be obvious    foreach static mesh in containerAllStaticMeshes // container that holds all static meshes    {          if seen by camera          {                SceneElement* pCurrentMesh = *containerAllStaticMeshes.iter;//obtain pointer                containerNotCulledStaticMeshes.insert(pCurrentMesh);//just insert pointer          }    }    ...    containerNotCulledStaticMeshes.sort(SceneElement::BackToFront());//sort meshes    foreach static mesh in containerNotCulledStaticMeshes    {           SceneElement* pElement = *containerNotCulledStaticMeshes.iter;//obtain pointer           SetShader();           pElement->Draw();    }}


Is there some kind of "container" for this?
Advertisement
std::vector.

.insert() = .push_back()

As for culling, it can be done in-place:
typedef std::vector<MeshFoo *> Meshes;Meshes meshes;Meshes::iterator i = std::partition(meshes.begin(), meshes.end(), IsVisible());std::sort(meshes.begin(), i, reverse_sort);std::for_each(meshes.begin(), i, DrawWithShader();
where the last parameters are relevant functors, for example:
struct IsVisible {  Camera * c;  bool operator()(MeshFoo * p) {    return c->can_see(p);  }};


Since vector contains pointers it doesn't allocate anything as such, but will expand as needed.
The second pass uses in-place (via partition) which avoids any extra allocations as well. It's also quite efficient.

Also, if at some point you feel like it, all of the calls above can be converted almost literally to something like TBB to allow concurrent processing. The above is as fast as it gets algorithmically, the rest would require understanding of actual data and organizing that.


As for removal - erase/remove_if is algorithmically optimal, single-pass method.


If the algorithms are coded generically, then all algorithms above work with plain arrays without change (baring the obvious push_back which needs to be implemented and iterator, which would be just plain pointer). There is no reason to do this unless data needs to be aligned_malloc()ed.
Why arent you using a smart pointer of some kind? such as a std::tr1::shared_ptr, boost::shared_ptr, or maybe even roll your own more specific smart pointer for resources?

eg.
std::vector<std::tr1::shared_ptr<ILight>> objectContainer;//...objectContainer.push_back(new DirectionalLight(...)) // blah, not sure if mixing different types is a good idea here..objectContainer.push_back(new PointLight(...)) // but its only example code so its all good :)objectContainer.push_back(...)


Then you wont have to loop through and manually delete all lights.. I dont know, I have an embaressingly small amount of experience with this kinda thing (ill get there someday) so umm maybe this isnt what you want. just a suggestion..
Quote:Original post by CodeCriminal
Why arent you using a smart pointer of some kind? such as a std::tr1::shared_ptr, boost::shared_ptr, or maybe even roll your own more specific smart pointer for resources?
There are many classes of problems where the life cycle of objects is well defined.

Create stuff in the beginning, keep updating for a while, cleanup everything.

shared_ptr is just that - pointer with shared ownership. In those cases it quickly becomes very tedious to keep track of who exactly must cleanup what. But with single owner and well defined entry and exit point, there is no need for that.

The only important gotcha is to either disable copying (assignment, copy constructor) or properly implement deep copy on the class holding the container. Otherwise actual objects may get deleted multiple times.
@Antheus
Quote:
...std::partition


YEESSSS. This is the thing that i was looking for. Thanks greatly for hint and clear explanation.

There is only one thing that i don't understand.
What "TBB" stands for? Is it something about multithreading?
Since i am still beginner i'll stick to just one until i learn more about it.
Quote:Original post by brega
What "TBB" stands for?
I'm not 100% sure, but based on the context I think it is this.

C++: A Dialog | C++0x Features: Part1 (lambdas, auto, static_assert) , Part 2 (rvalue references) , Part 3 (decltype) | Write Games | Fix Your Timestep!

for robust,please use boost library
by the way,in my game engine(site:www.sooftmoon.com) i use it a lot!

This topic is closed to new replies.

Advertisement