Monaにおける共有メモリへのアクセス方法

Monaにおける共有メモリへのアクセス方法をまとめます。
プロセス間で大きなデータをやり取りする場合は、メッセージ機能を利用するよりも共有メモリを利用するほうが効率が良いでしょう。(コピーやメッセージのオーバーヘッドがないため)

Monaの共有メモリは僕が書いたMemoryMapクラスでアクセスします。

class MemoryMap
{
public:
    static void initialize();
    static dword create(dword size);
    static byte* map(dword id);
    static bool unmap(dword id);
    static dword getLastError();
    static dword getSize(dword id);

こんな感じです。
ただこれはCからは呼べないし必要最低限のインターフェースしかないので、これを某氏がCからも利用可能にしてくれたAPIがあります。
プロセスAとプロセスBでデータを共有したいというシチュエーションでは以下のようなコードを書きます。

プロセスA

// monapi_cmemoryinfoの割り当て。この時点では共有メモリは作られていない
monapi_cmemoryinfo* mi = monapi_cmemoryinfo_new();

// sizeで指定された共有メモリを作成しプロセスAの空間にマップする
if (!monapi_cmemoryinfo_create(mi, size, prompt ? MONAPI_TRUE : MONAPI_FALSE))
{
    monapi_cmemoryinfo_delete(mi);
    return -1;
}

// この時点で以下の項目がセットされる
// mi->Handle: 共有メモリを一意に決定するHandle
// mi->Size: 共有メモリサイズ
// mi->Owner: 共有メモリのOwnerスレッドID
// mi->Data: プロセスAの空間における共有メモリの開始リニアアドレス

// ここでmi->Dataに対して書き込みを行う

// このメモリを共有したい相手(プロセスB)に mi->Handle, mi->Sizeをメッセージ機能を利用して送信する


// 共有メモリが不要になった場合
// 共有メモリをunmapする
// この時点で共有メモリへのアクセスはできなくなる
monapi_cmemoryinfo_dispose(mi);


// 構造体の後始末
monapi_cmemoryinfo_delete(mi);

プロセスB

// monapi_cmemoryinfoの割り当て。この時点では共有メモリは作られていない
monapi_cmemoryinfo* mi = monapi_cmemoryinfo_new();

// プロセスAからメッセージ機能を利用して 共有メモリHandle, sizeをうけとる
dword handle = xxxxx;
dword size  = xxxxx;

// 共有メモリをプロセスBの空間にマップする
mi->Handle = handle;
mi->Size   = size;
monapi_cmemoryinfo_map(mi);


// mi->DataにアクセスするとプロセスAが書き込んだものが読める・上書きできる

// 共有メモリが不要になった場合
// 共有メモリをunmapする
// この時点で共有メモリへのアクセスはできなくなる
// プロセスBは共有メモリのOwnerではないので、OwnerであるプロセスAにメッセージで
// MSG_DISPOSE_HANDLEとHandleを送信します。
monapi_cmemoryinfo_dispose(mi);

// 構造体の後始末
monapi_cmemoryinfo_delete(mi);

なお、共有メモリは参照カウンタを利用しているので各プロセスがmonapi_cmemoryinfo_disposeをして誰もmapしていない状態になったら破棄されます。