Returning data reference with mutex lock guard struct I'm writing a multi-threaded program where some external part of the program needs access to a large piece of data that's controlled by my class. I'm trying to return a reference to this data in a thread-safe way.
class Chunk
{
public:

    Chunk(){
        chunkData = std::make_shared&lt;vector&lt;XMFLOAT3&gt;&gt;();
        chunkMutex = std::make_shared&lt;std::mutex&gt;();
    };

    struct LockedData
    {
        LockedData(std::vector&lt;float&gt; const&amp; d, std::mutex&amp; mtx) : data(d), lk(mtx) {};
        std::vector&lt;XMFLOAT3&gt; const&amp; data;
    private:
        std::lock_guard&lt;mutex&gt;lk;
    };

    inline LockedData const&amp;&amp; RequestChunkData()const { return LockedData(*chunkData,chunkMutex); };

private:
    
    mutable std::shared_ptr&lt;std::mutex&gt; chunkMutex;
    std::shared_ptr&lt;vector&lt;float&gt;&gt; chunkData;

}

Is this over-complicated? will this actually protect my data, and am I using the rvalue references (&amp;&amp;) correctly?
Overview
This is not a good solution.
You are basically setting up a busy wait on the mutex.
You should be using a condition variable to give the OS the opportunity to reassign the processor to do other work.
Returning the LockedData is just making this much more complex than it needs to be. Use a get/release set of methods (but make them private) then use RAII to call get/release so that it is done correctly.
Code Review
class Chunk
{
    // I put private member variables at the top.
    // When writting the constructor I want to double check that
    // I have correctly set up all members.
    // I put all private methods at the bottom.
    // Not everybody agrees with me on this. But its what I like. :-)
    private:            
        mutable std::shared_ptr&lt;std::mutex&gt; chunkMutex;
        std::shared_ptr&lt;vector&lt;float&gt;&gt; chunkData;

    public:
    
        // Use the initializer list to set up members
        Chunk(){
            // I don't think these need to be shared dynamically like this.
            // Just make them members of chunk.
            chunkData = std::make_shared&lt;vector&lt;XMFLOAT3&gt;&gt;();
            chunkMutex = std::make_shared&lt;std::mutex&gt;();
        };


    
    
        // don't use `inline` here (it means nothing).
        // Dont add &amp;&amp; on the return type it does nothing.
        inline LockedData const&amp;&amp; RequestChunkData()const { return LockedData(*chunkData,chunkMutex); };
    
    
};

How I would do it:
class ChunkAccess;
class Chunk
{
    private:
        
        std::mutex              chunkMutex;
        std::condition_variable chunkCondition;
        std::vector&lt;float&gt;      chunkData;
        bool                    inUse;      

    public:
        Chunk()
            : inUse(false)
        {}
    private:
        friend class ChunkAccess;
        void getUniqueAccesses()
        {
            std::lock_guard&lt;mutex&gt;  lock(chunkMutex);
            chunkCondition.wait(lock, [&amp;inUse](){return !inUse;});
            inUse = true;
        }
        void releaseUniqueAccesses()
        {
            std::lock_guard&lt;mutex&gt;  lock(chunkMutex);
            inUse = false;
            chunkCondition.notify_one();
        }
};
class ChunkAccess
{
    private:
        Chunk&amp;  chunk;
    public:
        ChunkAccess(Chunk&amp; chunk)
            : chunk(chunk)
        {
            chunk.getUniqueAccesses();
        }
        ~ChunkAccess()
        {
            chunk.releaseUniqueAccesses();
        }
        // Don't want multiple access objects so prevent copy.
        ChunkAccess(ChunkAccess const&amp;)           = delete;
        ChunkAccess operator=(ChunkAccess const&amp;) = delete;
        // With a bit of tinkering you can make this moveable.

        // Simplify data accesses
        float&amp;       operator[](std::size_t index)       {return chunk.chunkData[index];}
        float const&amp; operator[](std::size_t index) const {return chunk.chunkData[index];}
};

int main()
{
    Chunk         data;
    ChunkAccess   dataAccess(data);

    std::cout &lt;&lt; dataAccess[3] &lt;&lt; &quot;\n&quot;;
}

How I could do (Option 2)
class Chunk
{
    private:
        
        std::mutex              chunkMutex;
        std::vector&lt;float&gt;      chunkData;

    public:
        Chunk()
            : inUse(false)
        {}

        void access(std::function&lt;void(std::vector&lt;float&gt;&amp;)&gt; const&amp; action)
        {
            std::lock_guard&lt;mutex&gt;  lock(chunkMutex);
            action(chunkData);
        }
};

int main()
{
    Chunk         data;
    data.access([](std::vector&lt;float&gt;&amp; value){
        std::cout &lt;&lt; value[3] &lt;&lt; &quot;\n&quot;;
    });
}