1

I am trying to share a structure across processes using interprocess in Boost.

I've defined the mapped file to use null mutex because I was having problems with it locking and I don't mind doing the synchronisation myself.

What I am having problems with though is finding of objects.

I have the following declaration:

typedef boost::interprocess::basic_managed_mapped_file
    < char,
    boost::interprocess::rbtree_best_fit<boost::interprocess::null_mutex_family,boost::interprocess::offset_ptr<void>>,
    boost::interprocess::flat_map_index>
    my_mapped_file;

In process A, I do:

m_managedMappedFile.reset(new my_mapped_file(bip::open_or_create, filename, filesize));
auto hdr = m_managedMappedFile->find_or_construct<Foo>(bip::unique_instance)();
auto x = m_managedMappedFile->find<Foo>(bip::unique_instance);

Which works as I would expect, i.e. it finds the object. Now, in process B:

    m_managedMappedFile.reset(new my_mapped_file(bip::open_only, filename));
    auto ret = m_managedMappedFile->find<Foo>(bip::unique_instance);

For some reason the find method returns null in process B. I realise I must be doing something daft, but can't figure it out.

Can anyone help?

Dave F
  • 973
  • 9
  • 19
  • How are you locking/synchronizing? Because you better know what you're doing. I've never had need to circumvent the locking at the level of `managed_mapped_file` – sehe Feb 09 '15 at 15:41
  • @sehe If I didn't use the null mutex, I simply couldn't get it to work; doing a find_or_construct(unique_instance)() works, but then a find(unique_instance) in the other process, it would hang waiting on the mutex (in priv_generic_find), even if process A had terminated! – Dave F Feb 09 '15 at 16:02
  • What is the platform, library/compiler versions? – sehe Feb 09 '15 at 16:03

1 Answers1

1

You should not have to bypass the locking mechanism of the default bip::managed_mapped_file indexes.

See if you can run the following with success:

#include <iostream>
#include <boost/interprocess/managed_mapped_file.hpp>

namespace bip = boost::interprocess;

struct X {
    int i;
};

int main()
{
    {
        bip::managed_mapped_file f(bip::open_or_create, "/tmp/mmf.bin", 1ul << 20);

        if (!f.find<X>(bip::unique_instance).first) {
            auto xp = f.find_or_construct<X>(bip::unique_instance)();

            assert(xp);
            xp->i = 42;
        }
    }

    {
        bip::managed_mapped_file f(bip::open_only, "/tmp/mmf.bin");
        auto xp = f.find<X>(bip::unique_instance).first;

        if (xp)
            std::cout << "value: " << xp->i++ << "\n";
    }
}

This should print 42 on the first run (or after the file has been recreated), and increasing numbers on each subsequent run.

I'm going to have a look at the implementation behind the unique_instance_t* overloads of the segment managers, but I suspect they might not work because the mutex policy was nulled. This is just a hunch though, at the moment.

I'd focus on finding out why you can't get Interprocess managed_mapped_file working in the default configuration, on your platform & installation.

sehe
  • 374,641
  • 47
  • 450
  • 633
  • 1
    Thank you very much for your help - I was in the process of getting the compiler/library versions for you, and I realised that my main application was 64 bit and my test application was 32 bit - that was (understandably) confusing things. Thanks once again! – Dave F Feb 09 '15 at 16:23
  • 1
    That makes sense indeed, since it looks that since at least [here](https://svn.boost.org/trac/boost/ticket/10011) the `unique_instance_t` method uses the `typeid(T).name()` which will be different :) – sehe Feb 09 '15 at 16:25
  • 1
    (Actually, strike that. Sharing C++ classes across processes with different ABIs will simply be Undefined Behaviour. I don't think Boost Interprocess detects this and avoids it) – sehe Feb 09 '15 at 16:30