0

I'm trying to create a vector of objects in shared memory that each own an interprocess_mutex as follows:

struct test
{
    test(){}
    interprocess_mutex mutex;
};

using namespace boost::interprocess;
managed_shared_memory seg(open_or_create, "MySharedMemory", 65536);
allocator<void, managed_shared_memory::segment_manager> void_alloc_(seg.get_segment_manager());
vector<test, allocator<test, managed_shared_memory::segment_manager>> vec(void_alloc_);
vec.push_back(test());

However interprocess_mutex is explicitly missing a copy/move constructor and clang fails to compile with this error:

copy constructor of 'test' is implicitly deleted because field 'mutex' has an inaccessible copy constructor
interprocess_mutex mutex;

Is there a reason for this? It looks like boost::thread mutex has a copy constructor. How can I accomplish this using interprocess_mutex?

jondo2010
  • 71
  • 6

2 Answers2

0

No standard or Boost mutex-type class provides a copy constructor. If you need to copy classes containing a mutex member, the mutex needs to be turned into a pointer, and you need to provide a copy constructor to deal with the mutex appropriately.

What would copying a mutex even do? Would both instances refer to the same mutex? Would each instance have it's own mutex? What if the mutex is already locked during the copy?

Aside from these questions, a mutex member is often used to protect the object's other members. If you support copying on a class with a mutex member, you very likely want to lock that mutex at some point during the copy.

Collin Dauphinee
  • 13,664
  • 1
  • 40
  • 71
  • I came across this question while trying to move a boost interprocess mutex. Would you happen to know why that is not possible? – pooya13 Nov 02 '21 at 20:28
0

I solved the problem by changing the vector to contain shared_ptr instead of test directly. test() gets called only once and the object is owned by the shared_ptr object, which is move/copyable:

    using namespace boost::interprocess;

    typedef managed_shared_memory::segment_manager SegmentManager;
    typedef allocator<void, SegmentManager> test_allocator;
    typedef deleter<test, SegmentManager> test_deleter;
    typedef shared_ptr<test, test_allocator, test_deleter> test_pointer;
    typedef vector<test_pointer, allocator<test_pointer, SegmentManager>> test_pointer_vector;

    managed_shared_memory seg(open_or_create, "MySharedMemory", 65536);

    test_allocator alloc(seg.get_segment_manager());
    test_deleter del(seg.get_segment_manager());

    test_pointer& p = *seg.construct<test_pointer>(anonymous_instance)(seg.construct<test>(anonymous_instance)(), alloc, del);
    test_pointer_vector& vec = *seg.construct<test_pointer_vector>(anonymous_instance)(alloc);

    vec.push_back(p);
    p.get()->mutex_.try_lock();
jondo2010
  • 71
  • 6