samedi 20 février 2016

Need advise for finding correct Implementation for WrapperInterface in c++ (rule of three)

I try to find a working pattern for an interface.

Some information of what i'm doing. I'm implementing a rendering engine in dx11. My goal is to provide an easy and highly interfaced engine, where the client does not have to have any knowledge of dx11 or advanced rendering techniques.

I have my Engine and that engines provides functions to set and create any objects, terrain, sun, lighting, water, horizon and and and.

Now i come to my question. My so called MeshController of the engine provides these 3 methods (code is simplified):

//check if that description already exists (if not create it) and return that id
UINT addDesc(const MESH_ENTITY_DESC& desc);

//create an instance of the given object
MeshEntity* createInstance(const UINT descID);

//destroy the instance
void destroyInstance(MeshEntity* entity);

To avoid the clients to deal with pointers, i try to pack that in a wrapper class, that will do nullptr checks, check if entity is already destroyed or already created and so on.

Wrapper:

class MeshObject
{
    private:
    UINT g_Desc;
    MeshEntity* g_Entity;
}

Now i want the object to be always in a valid state. If the instance is not destroyed before losing the wrapper object, it will create a memory leak (not really, but my controller will render it until the scene is closed, or will block an instance slot, all in all the client will lose control over the instance). So my first thought was this:

//constructor
MeshObject(const MESH_ENTITY_DESC& desc)
{
     g_Desc = Controller::addDesc(desc);
     g_Entity = Controller::createInstance(g_Desc);
}

//copy constructor
MeshObject(const MeshObject& mo)
{
    g_Desc = mo.g_Desc;   //no need of adding desc, already exists
    g_Entity = g_Entity;  // no need of recreation? or should i also create a copy of the rendered object in the controller, so duplicate it?
}

MeshObject& operator=(const MeshObject& mo)
{
    g_Desc = mo.g_Desc;   //no need of adding desc, already exists
    g_Entity = g_Entity;  // definitly no need of recreation
}

~MeshObject()
{
    Controller::destroyInstance(g_Entity);
}

Due to the rule of three, i need the copy and the assignment operators. But there's the problem. The createInstance and destroyInstance methods have a lot of overhead, because of adding/deleting to/from scene, maybe recreating render buffers ...

So now i try to find any way to prevent the object from being destroyed, if it was copied before, or if there is a valid reference(pointer) to it. It's not a typical dynamic memory allocation, but some sort of allocation in my controller.

typical usecase of the client:

std::vector<MeshObject> moVector;
for(int i = 0; i < blabla; i++)
{
    MeshObject mo(someDescription); // created object in controller

    //do lot of init stuff, like position, rotation, ...

    mo.pushback(mo); // here mo will be copied, try to avoid double creation
} // here mo will lose scope and will be destroyed, stop destroying because there is a valid wrapper object

Here is some image for motivation^^ Image of my rendering engine

Thanks for any help!

Aucun commentaire:

Enregistrer un commentaire