Managed Memory Segments 小ネタ幾つか

今日は特にネタがなかったので、Managed Memory Segmentsが提供してる機能をいくつか書いておきます。とりあえずManaged Memory Segments上のお話なので前提条件を書きます。変数名はmm_segmentsで、オブジェクトは自動で削除されます。ちなみに、ドキュメントの内容をいくつかかいつまんで書いてる部分が多いです。今回の話はBoost.interprocess Document PDFのP.76 [Managed Memory Segment Advanced Features]で書かれている内容です。

namespace bip = boost::interprocess;

// メモリのサイズ
static const std::size_t MemorySize = 65536;
// 以上の条件で開く
bip::managed_shared_memory mm_segments(bip::create_only,"MyMemorySegments",MemorySize);

なんだか使えそうなユーティリティメソッド

// Memory Segmentsのサイズ(今回は65536byte)
mm_segments.get_size();

// 現在フリー領域になっているサイズ
mm_segments.get_free_memory();

// フリー領域のメモリをすべて0に初期化
// (恐らく変なデータが残ってないようにするため)
mm_segments.zero_free_memory();

// 全てdeallocateされているか(何かallocateされている領域が1つもないか)
mm_segments.all_memory_deallocated();

// このSegments内の内部状態をチェックする。エラー無く通ればtrueを返却
mm_segments.check_sanity();

// それぞれNamed ObjectとUnique Objectの数を取得
mm_segments.get_num_named_objects();
mm_segments.get_num_unique_objects();

all_many_deallocatedとget_num_unique_objectsはよくわかってません。誰か教えてください。
unique、というのはconstruct<>メソッドの引数にbip::unique_instanceを渡した際に作成できるようです。

Alignment指定Allocate

Allocate時、Alignmentを指定することも可能です。

const std::size_t Alignment = 128;
// 100byteをAlignment128byteでAllocateする(nothrow版)
void* ptr = mm_segments.allocate_aligned(100,Alignment,std::nothrow);

assert( static_cast<char*>(ptr) - static_cast<char*>(0) % Alignment == 0 );

// 削除
mm_segments.deallocate(ptr);

Allocate用の関数はnothrow版が用意されており、便利だったりします。

Multiple Allocate

例えば、Nbyte確保したものをM個用意したい場合、ループ回したりすると思いますが、allocate_manyで向こうが確保したメモリをmultiallocation_iteratorというイテレータとして返してくれます。これを使うのですが、multiallocation_chainというちょっとしたラッパがあるようなのでこっちを使った方が良さそうです。

typedef managed_shared_memory::multiallocation_chain multiallocation_chain;

// 32byteの領域を8個確保(nothrow版)
multiallocation_chain chain(mm_segments.allocate_many(32,8,std::nothrow));
// 戻り値のイテレータが有効領域を指しているかチェック
if( !chain.empty() ) return -1;

// 確保した領域を何かしらのバッファへ保存し直しながら初期化
std::vector<void*> allocate_buffer;
while( !chain.empty() )
{
    void* p = chain.front();
    chain.pop_front();
    allocate_buffers.push_back(p);
    std::memset(p,0,100);
}

// 通常のallocateと同様にポインタを渡してdeallocateできる
while( !allocate_buffer.empty() )
{
    mm_segments.deallocate(allocate_buffer.back());
    allocate_buffer.pop_back();
}

// もちろん、allocate_many用のdeallocate_manyもある
// mm_segments.deallocate_many(bip::move(chain));

実際のところ使いにくそうな気がするんだが…。many版でなくてもdeallocateできるのはまあ良しとして。

これ書いてる途中でunique_instanceだのanonymous_instanceだの色々見つけたんですが、結構長くなりそうな予感がしたのでまた次の機会に。