2

I am suffering from the problem that I need a named_mutex for a managed_shared_memory member within a class and get a "cannot access private member declared in class boost::interprocess::named_mutex" error. However, I both derived my class from boost::noncpoyable and used a std::unique_ptr with move-semantic in the constructor, without success. Using boost 1_60 and VS 2010, code follows:

class FileLocker : private boost::noncopyable
{
public:
    FileLocker();
    ~FileLocker();

private:
    boost::interprocess::managed_shared_memory m_oShMem;
    std::unique_ptr<boost::interprocess::named_mutex> m_oSetFileMutex;  
};

cpp-file:

FileLocker::FileLocker()
{
  m_oShMem = managed_shared_memory(open_or_create, m_oMemName.c_str(), 1024);
  m_oSetFileMutex = make_unique<named_mutex>( m_oShMem.find_or_construct<named_mutex>("viVideoFileInOutMutex")() );
}

and finally make-unique:

template<typename T>
std::unique_ptr<T> make_unique()
{
    return std::unique_ptr<T>( new T() );
}

template<typename T, typename Ts>
std::unique_ptr<T> make_unique(Ts&& params)
{
    return std::unique_ptr<T>( new T(std::forward<Ts>(params)) );
}

I read several Stackoverflow-Threads regarding the problem, but all of them point out the non-copyability which imho I have dealt with...

Thanks for help!

gilgamash
  • 862
  • 10
  • 31

2 Answers2

2

Leaving aside other issues, you are calling named_mutex constructors incorrectly in two places.

One of them is here:

m_oShMem.find_or_construct<named_mutex>("viVideoFileInOutMutex")()

The string parameter you're passing is the name of the object in the shared memory, but it doesn't get passed to the constructor of the actual object, named_mutex in this case. So this basically leads to a call to the default constructor of named_mutex, which is private. To pass parameters to the constructor of the underlying object, you have to send them like this:

m_oShMem.find_or_construct<named_mutex>("viVideoFileInOutMutex")(open_or_create, "named_mutex_name")

in the second set of parenthesis.

The second problem starts on the same line:

m_oSetFileMutex = make_unique<named_mutex>( m_oShMem.find_or_construct<named_mutex>("viVideoFileInOutMutex")(open_or_create, "named_mutex_name") );

This is basically equivalent to this:

named_mutex *temp = m_oShMem.find_or_construct<named_mutex>("viVideoFileInOutMutex")(open_or_create, "named_mutex_name") );
m_oSetFileMutex = make_unique<named_mutex>(temp);

You already have a raw pointer to a named_mutex, that you're passing to make_unique. This leads to make_unique calling a constructor of named_mutex taking a named_mutex* as a parameter. Such a constructor doesn't exist.

Ionut
  • 6,436
  • 1
  • 17
  • 17
  • Ah. I didn't even see the find or construct. This will probably help the OP figure it the missing bit. +1 – sehe Mar 04 '16 at 15:23
  • Thanks a lot for this information, I will try this as soon as I get back to the problem (Monday)! – gilgamash Mar 05 '16 at 06:03
  • Despite the fact that you put the mutex name in the shared mem place, your answer was absolutely correct and helped solving the problem. Thanks! – gilgamash Mar 07 '16 at 11:10
0

Firstly, boost::noncopyable is not movable. Therefore, unless you write your custom move constructor/assignment (Rule Of Five) you will never get a movable type. The compiler can't generate default move special members if the base is not movable.

Here's the naively fixed class:

Live On Coliru

#include <memory>
#include <boost/interprocess/sync/named_mutex.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>

class FileLocker
{
public:
    FileLocker() { }
    ~FileLocker() { }

    // non-copyable:
    FileLocker(FileLocker const&)             = delete; // noncopyable
    FileLocker& operator==(FileLocker const&) = delete; // noncopyable

    // movable
    FileLocker(FileLocker&&) = default;

private:
    boost::interprocess::managed_shared_memory m_oShMem;
    std::unique_ptr<boost::interprocess::named_mutex> m_oSetFileMutex;  
};

int main() {
    FileLocker fl;
    auto moved = std::move(fl);
}

But given the fact that managed_shared_memory is already non-copyable, you could leverage Rule Of Zero:

Live On Coliru

#include <memory>
#include <boost/interprocess/sync/named_mutex.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>

class FileLocker {
    boost::interprocess::managed_shared_memory m_oShMem;
    std::unique_ptr<boost::interprocess::named_mutex> m_oSetFileMutex;  
};

int main() {
    FileLocker fl;
    auto moved = std::move(fl);

    //auto copy = moved; // doesn't compile
}
sehe
  • 374,641
  • 47
  • 450
  • 633
  • Hi and thanks for the answer. =delete, =default are not available in VS 2010. I tried reimplementing the copy constructor, but the (negative) results remained unchanged. However, I fotgot about the && version. I will try inlcluding all of those in the private section (old way) and get back afterwards! – gilgamash Mar 04 '16 at 14:15
  • You sound horribly confused. Here's the c++11-dumbed version: http://coliru.stacked-crooked.com/a/98473fe0ce08ec87 – sehe Mar 04 '16 at 14:20
  • Nope, I am not confused. I just forgot the && version of the = operator, which I have added (basically identical to your suggestion, but implemented in the cpp file). The "cannot access private member" error is still showing up. – gilgamash Mar 04 '16 at 14:36