IPDL/Shmem
Introduction
IPDL provides a built-in Shmem type. Shmem represents a segment of memory mapped into both a parent's and child's address space. Shmems are used to avoid copying large amounts of data across the IPC pipe.
Ownership model
The model is very simple: at any given time, a Shmem is owned by either the parent or the child. Only the owner has read/write privileges; the other side has no privileges. One side transfers ownership of a Shmem to the other by sending the Shmem in an IPDL message, or returning it in a reply to a synchronous message.
It's illegal for C++ code to read/write a Shmem it doesn't own. We enforce ownership semantics by mapping segments with full read/write access in the owning process, and mapping them with no access in the other process. C++ code that violates the ownership model will die from a SEGFAULT.
Using Shmem in protocols
sync protocol UsesShmem {
child:
// transfers ownership of |s| from parent to child
HereYouGo(Shmem s);
parent:
// transfers ownership of |s| from child to parent, then back to child
GiveAndGetBack(Shmem s) returns (Shmem ss);
// transfers ownership of |s| from child to parent
ThanksDone(Shmem s);
};
WARNING: there's currently a bug in the IPDL compiler that needs to be worked around (the bug should be fixed "soon"). If you use Shmem in a managed (i.e. not top-level) protocol, then the top-level protocol needs to use Shmem as well. You can work around this with the following hack
protocol TopLevel {
parent: Dummy(Shmem _);
// etc.
};
Using Shmem in C++
class Foo : public UsesShmemParent {
using mozilla::ipc::Shmem;
Shmem mShmem;
bool Init() {
// this may fail; always check return value
if (!AllocShmem(&mShmem, 10000))
return false;
// get() and Size() check for proper alignment of the segment
memset(mShmem.get<char>(), 0, mShmem.Size<char>());
}
bool Foo() {
// [do stuff]
char* p = mShmem.get<char>();
if (!SendHereYouGo(mShmem))
return false;
// mShmem is now unusable; both of the following would fail:
// *p = 1;
// mShmem.get<char>();
}
NS_OVERRIDE virtual bool
RecvGiveAndGetBack(Shmem& s, Shmem* ss) {
// we own |s| again
// [do stuff with |s|]
*ss = s;
// when this method returns, we don't own |s| anymore
}
NS_OVERRIDE virtual bool
RecvThanksDone(Shmem& s) {
// we own |s| again
mShmem = s;
}
};
Shmems are automatically managed by IPDL-generated code. When your protocol tree is deleted, all Shmems still open are unmapped and deleted.
Aside: it's not necessary to know this, but Shmems are actually just handles to other objects managed by IPDL-generated code.