nlib
nn::nlib::LockFreeUnitHeap クラスfinal

固定メモリサイズの領域を確保・解放をロックフリーで行うことのできるプールアロケータです。 [詳解]

#include "nn/nlib/LockFree.h"

公開メンバ関数

MemHolder * Alloc () noexcept
 メモリを割り当てます。スレッドセーフです。 [詳解]
 
void Free (MemHolder *p) noexcept
 メモリを解放します。スレッドセーフです。 [詳解]
 
MemHolder * AllocUnsafe () noexcept
 Alloc()と同様ですが、スレッドセーフではありません。 [詳解]
 
void FreeUnsafe (MemHolder *p) noexcept
 Free()と同様ですが、スレッドセーフではありません。 [詳解]
 
void SwapUnsafe (LockFreeUnitHeap &rhs) noexcept
 オブジェクトをスワップします。スレッドセーフではありません。
 
コンストラクタ、デストラクタ、及び初期化
 LockFreeUnitHeap () noexcept
 デフォルトコンストラクタです。
 
errno_t Init (size_t unit_size, size_t align, size_t count) noexcept
 アロケータを初期化します。スレッドセーフではありません。 [詳解]
 
 ~LockFreeUnitHeap () noexcept
 デストラクタです。
 

詳解

固定メモリサイズの領域を確保・解放をロックフリーで行うことのできるプールアロケータです。

説明
通常、malloc(), free()等は内部でスレッドがブロックされる可能性がありますが、LockFreeUnitHeapはブロックする可能性なしにメモリの取得、解放を行うことができます。 スレッドがブロックされることが容認できない場合や、サイズが同一で比較的大きいサイズのメモリを動的に取得、解放したい場合にこのクラスの利用を検討するとよいでしょう。
以下がコード例です。kBlockCount個の割り当て可能領域数を持つアロケータを作成し、kNumThread個のスレッドからアロケートしています。
struct MemoryBlock { char data[32]; };
const int kBlockCount = 1024;
e = heap.Init(sizeof(MemoryBlock), 32, kBlockCount);
SUCCEED_IF(e == 0);
e = stack.Init(kBlockCount);
SUCCEED_IF(e == 0);
const int kNumThread = 16;
std::thread th_list[kNumThread];
for (auto& th : th_list) {
th = std::thread([&]() {
for (int i = 0; i < kBlockCount / kNumThread; ++i) {
auto holder = heap.Alloc();
stack.Push(reinterpret_cast<uintptr_t>(holder));
}
});
}
for (auto& th : th_list) { th.join(); }
uintptr_t vec[kBlockCount];
for (int i = 0; i < kBlockCount; ++i) {
uintptr_t item = 0;
e = stack.PopUnsafe(&item);
SUCCEED_IF(e == 0);
vec[i] = item;
}
std::sort(&vec[0], &vec[0] + kBlockCount);
auto it = std::unique(&vec[0], &vec[0] + kBlockCount);
SUCCEED_IF(it == &vec[0] + kBlockCount); // confirm they are all different
for (auto& ptr : vec) {
heap.FreeUnsafe(reinterpret_cast<decltype(heap.Alloc())>(ptr));
}

LockFree.h783 行目に定義があります。

関数詳解

◆ Alloc()

nn::nlib::LockFreeUnitHeap::Alloc ( )
inlinenoexcept

メモリを割り当てます。スレッドセーフです。

戻り値
割り当てが成功した場合はNULL以外のポインタ
説明
戻り値の型(MemHolder)はこのクラスの内部クラスで、Get()メンバ関数だけが利用できるクラスです。 返されたオブジェクトへのポインタに対してGet()を実行して戻り値を取得することで割り当てた領域を得ることができます。

LockFree.h800 行目に定義があります。

◆ AllocUnsafe()

nn::nlib::LockFreeUnitHeap::AllocUnsafe ( )
inlinenoexcept

Alloc()と同様ですが、スレッドセーフではありません。

戻り値
割り当てが成功した場合はNULL以外のポインタ

LockFree.h811 行目に定義があります。

◆ Free()

nn::nlib::LockFreeUnitHeap::Free ( MemHolder *  p)
inlinenoexcept

メモリを解放します。スレッドセーフです。

引数
[in]pAlloc()の戻り値

LockFree.h804 行目に定義があります。

◆ FreeUnsafe()

nn::nlib::LockFreeUnitHeap::FreeUnsafe ( MemHolder *  p)
inlinenoexcept

Free()と同様ですが、スレッドセーフではありません。

引数
[in]pAlloc()の戻り値

LockFree.h815 行目に定義があります。

◆ Init()

nn::nlib::LockFreeUnitHeap::Init ( size_t  unit_size,
size_t  align,
size_t  count 
)
noexcept

アロケータを初期化します。スレッドセーフではありません。

引数
[in]unit_size確保したい領域の1つあたりのサイズ
[in]align確保したい領域のアライメント
[in]count割り当てることのできる領域数の最大値
戻り値
0成功した場合
ENOMEMメモリの確保に失敗した場合
EINVALアライメントが2のべき乗ではなかった場合

このクラス詳解は次のファイルから抽出されました: