Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to move an object from one vector to another, without destroying any?

I have a vector of objects that represent GPU resources. I ended up with a pretty dangerous scenario: the objects can only be safely created or destroyed in a specific thread, but another thread still needs to be able to move them around between vectors.

As a safeguard, I deleted their copy constructor, copy assignment, and move assignment methods; the only method that isn’t deleted is their move constructor.

Is there a way I can move an object like this from the middle of one vector, to the back of another vector?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

class MappedBuffer {
public:
    MappedBuffer(GLuint name, char * mapping) : m_name(name), m_mapping(mapping) {
        assert(std::this_thread::get_id() == RENDER_THREAD_ID);
    };
    MappedBuffer(MappedBuffer && other) : m_name(other.m_name), m_mapping(other.m_mapping) {
        other.m_name = 0;
        other.m_mapping = 0;
    }
    MappedBuffer(const MappedBuffer & other) =delete;
    MappedBuffer & operator=(MappedBuffer && other) =delete;
    MappedBuffer & operator=(const MappedBuffer & other) =delete;
    ~MappedBuffer() {
        assert(m_name == 0 || std::this_thread::get_id() == RENDER_THREAD_ID);
        if (m_name) {
            gl::buffer::unmap(m_name);
            gl::buffer::dealloc(m_name);
        }
    }

private:
    char * m_mapping    {0}; // directly points to GPU memory
    GLuint m_name       {0};
};


// not the render thread
int f(size_t srcIndex, std::vector<MappedBuffer> & src, std::vector<MappedBuffer> & dest) {

    // how could someone do something like the following, but without destroying any of the objects?
    dest.push_back(src.begin() + srcIndex);
    dest.erase(src.begin() + srcIndex);
    
}

>Solution :

Two vectors do not share an allocation (except if one is move-constructed/-assigned from the other).

Therefore moving between vectors implies creating a new object in the new vector’s allocation and destroying the one in the old allocation.

Only node-based containers offer an interface to reassign elements between containers without a move of the stored object, e.g. std::list::splice.

The alternative is to add an indirection to the vector, by storing pointers (of whatever kind) to the objects instead of the objects themselves in it.

Without indirection per element this can’t work.


You can’t insert into the vector either under these constraints. Insertion may cause reallocation and consequently move and destruction of objects.


However, the type you are showing already contains an indirection via the char* pointer. Your class sets m_name to zero and therefore an "empty" state if it is moved-from and the destructor won’t actually do anything. So destruction after a move is completely safe. The move assignment can simply behave in exactly the same way. And then there won’t be any issue at all.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading