c++multithreadingmutexmemcpy

Copying heap allocated memory in multiple threads... Is a mutex required or is it safe?


Environment is Ubuntu 24.04, QT Creator 6, g++ 13.3, pthreads.

Given the following code (error handling has been removed for readability):

#include <iostream>
#include <thread>
#include <cstring>

#define HEAPBUFFER  (100000)

class Foo {
public:
    Foo() {
        foo_buffer = nullptr;                           //Construct to null
    }
    ~Foo(){
        std::cout<<"Deleting instance heap"<<std::endl;
        delete [] foo_buffer;                           //Release the heap
    }
    void take_copy(u_int8_t *heap_to_copy, int len) {
        foo_buffer = new u_int8_t[len];                 //Allocate on the heap
        buf_len = len;                                  //Store the length internally

        //At this point here, if this is running in one or more seperate threads, does this need to have mutex protection locked?
        std::memcpy(foo_buffer, heap_to_copy, buf_len); //Copy from the "global" heap allocation to the "local" heap allocation
        //At this point here, if this is running in one or more seperate threads, does this need to have mutex protection released?
    }

private:
    u_int8_t    *foo_buffer;
    int buf_len;
};

u_int8_t    *heap_buffer;


int main()
{
    Foo foo;
    Foo bar;

    heap_buffer = new u_int8_t[HEAPBUFFER];                         //Allocate on heap, sets to 0x00

    std::memset(heap_buffer, 0xFF, sizeof(u_int8_t)*HEAPBUFFER);    //Set to 0xFF

    std::thread take_copy_one(&Foo::take_copy, &foo, heap_buffer, HEAPBUFFER);                         //Take a copy for foo to use
    std::thread take_copy_two(&Foo::take_copy, &bar, heap_buffer, HEAPBUFFER);                         //Take a copy for foo to use

    //If I decide to do something here to heap_buffer, I'm guess there needs to be some shared mutex protection or bad things may happen?
    take_copy_one.join();
    take_copy_two.join();

    delete [] heap_buffer;                                          //Release the memory

    return 0;
}

I have allocated heap memory, I then instantiate two objects of "Foo". These two objects require a copy of the heap allocated memory in order to perform some computation. In this simple example, the heap is untouched in the main thread as my question here relates purely to the std::memcpy function.

I am aware that in the real world, the main thread may well change the heap memory and would need some kind of synchronisation across the threads, but I'm ignoring that in this instance.

However, my questions to those cleverer than me are:

  1. In the case of the code above, would the std::memcpy call in the two thread require a mutex around them?
  2. If a mutex is required, this would need to be a shared mutex, i.e. I couldn't just use an instance level mutex, it would have to be declared "globally" and a reference to it passed to the instance, either via the constructor or the take_copy method?

I'm very unclear on this. My thoughts are that, because it is a copy, i.e. the shared heap memory is being read (not written), then the two std::memcpy calls will be "safe".


Solution

    1. In the case of the code above, would the std::memcpy call in the two thread require a mutex around them?

    No.

    As long as there is a guarantee that what the reading threads read will not be written to while the reading is done, any number of threads can do the reading simultaneously without extra synchronization. This goes for std::memcpy as well as loops doing the reading piecewise. What you've demonstrated in your example is therefore safe.