nlib
nn::nlib::LockFreePriorityQueue< T > クラステンプレートfinal

ロックフリーな優先度つきキューを実装したクラスで、nlib_mqをラップしています。 [詳解]

#include "nn/nlib/LockFree.h"

公開型

typedef UniquePtr< T, DestructorForLockFree< T > > DequeueType
 Dequeue()の引数となる型です [詳解]
 

公開メンバ関数

errno_t Close () noexcept
 キューをクローズし初期化前の状態にします。スレッドセーフではありません。 [詳解]
 
errno_t Enqueue (T *obj, int prio) noexcept
 キューに要素を追加します。スレッドセーフです。 [詳解]
 
errno_t Dequeue (DequeueType &obj, int *prio) noexcept
 キューから要素を取り出します。スレッドセーフです。 [詳解]
 
void SwapUnsafe (LockFreePriorityQueue &rhs) noexcept
 オブジェクトをスワップします。スレッドセーフではありません。
 
コンストラクタ、デストラクタ、及び初期化
 LockFreePriorityQueue () noexcept
 デフォルトコンストラクタです。
 
 ~LockFreePriorityQueue () noexcept
 デストラクタです。 [詳解]
 
errno_t Init (size_t max_size) noexcept
 キューを初期化します。スレッドセーフではありません。 [詳解]
 

詳解

template<class T>
class nn::nlib::LockFreePriorityQueue< T >

ロックフリーな優先度つきキューを実装したクラスで、nlib_mqをラップしています。

テンプレート引数
Tキューの要素の型です。
説明
必要な場合はDestructorForLockFree<T>を特殊化して、要素型Tを解体するコードを記述する必要があります。 また、Dequeue()の実行中にEnqueue()が実行された場合、Dequeue()が最高優先度の要素を返さない場合があります。
以下がコード例です。kNumThread個のスレッドからタスクが送信され、kNumThread個のスレッドで受信しますが、キューに存在する優先度の高いタスクから受信します。
struct Task {
const char* text;
int threadid;
};
errno_t e = queue.Init(512);
SUCCEED_IF(e == 0);
const int kNumThread = 3;
std::thread receiver_thread_list[kNumThread];
for (auto& th : receiver_thread_list) {
th = std::thread([&]() {
for (int i = 0; i < 8; ++i) {
int prio;
while (queue.Dequeue(item, &prio) != 0) { nlib_yield(); }
nlib_printf("Receiver(%d) receives '%s' from Sender(%d)\n",
GetMyThreadId(), item->text, item->threadid);
}
});
}
std::thread sender_thread_list[kNumThread];
for (auto& th : sender_thread_list) {
th = std::thread([&]() {
const char* text_list[] = {
"Low priority task",
"Normal priority task",
"High priority task"
};
std::random_device rd;
std::mt19937 mt(rd());
std::uniform_int_distribution<int> dice(0, 2);
for (int i = 0; i < 8; ++i) {
int prio = dice(mt);
std::unique_ptr<Task> task(new (std::nothrow) Task());
task->text = text_list[prio];
task->threadid = GetMyThreadId();
Task* p = task.release();
while (queue.Enqueue(p, prio) != 0) { nlib_yield(); }
}
});
}
for (auto& th : sender_thread_list) { th.join(); }
for (auto& th : receiver_thread_list) { th.join(); }
(void)queue.Close();
/*
Output:
Receiver(23616) receives 'High priority task' from Sender(19036)
Receiver(2472) receives 'High priority task' from Sender(19036)
Receiver(16612) receives 'Normal priority task' from Sender(19036)
Receiver(23616) receives 'High priority task' from Sender(19036)
Receiver(2472) receives 'High priority task' from Sender(19036)
Receiver(16612) receives 'High priority task' from Sender(1612)
Receiver(23616) receives 'High priority task' from Sender(1612)
Receiver(2472) receives 'High priority task' from Sender(1612)
Receiver(16612) receives 'High priority task' from Sender(23708)
Receiver(23616) receives 'High priority task' from Sender(23708)
Receiver(2472) receives 'Normal priority task' from Sender(19036)
Receiver(16612) receives 'Normal priority task' from Sender(19036)
Receiver(23616) receives 'Normal priority task' from Sender(19036)
Receiver(2472) receives 'Normal priority task' from Sender(1612)
Receiver(16612) receives 'Normal priority task' from Sender(1612)
Receiver(23616) receives 'Normal priority task' from Sender(1612)
Receiver(2472) receives 'Normal priority task' from Sender(23708)
Receiver(16612) receives 'Normal priority task' from Sender(23708)
Receiver(23616) receives 'Normal priority task' from Sender(23708)
Receiver(2472) receives 'Low priority task' from Sender(1612)
Receiver(23616) receives 'Low priority task' from Sender(23708)
Receiver(16612) receives 'Low priority task' from Sender(1612)
Receiver(2472) receives 'Low priority task' from Sender(23708)
Receiver(16612) receives 'Low priority task' from Sender(23708)
*/

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

型定義メンバ詳解

◆ DequeueType

Dequeue()の引数となる型です

説明
DestructorForLockFreeで自動的にデストラクトされるようにUniquePtrがtypedefされています。

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

構築子と解体子

◆ ~LockFreePriorityQueue()

template<class T>
nn::nlib::LockFreePriorityQueue< T >::~LockFreePriorityQueue ( )
inlinenoexcept

デストラクタです。

説明
要素が残っている場合は、それぞれの要素をDestructorForLockFreeを利用して削除します。 必要な場合は関数テンプレートを特殊化して必要な処理を実行してください。

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

関数詳解

◆ Close()

template<class T>
nn::nlib::LockFreePriorityQueue< T >::Close ( )
inlinenoexcept

キューをクローズし初期化前の状態にします。スレッドセーフではありません。

戻り値
0ならば成功
説明
キューに要素が残っている場合はDestructorForLockFree<T>によりデストラクトされます。

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

◆ Dequeue()

template<class T>
nn::nlib::LockFreePriorityQueue< T >::Dequeue ( DequeueType obj,
int *  prio 
)
inlinenoexcept

キューから要素を取り出します。スレッドセーフです。

引数
[out]objキューから取り出されたオブジェクト
[out]prioobjの優先度
戻り値
nlib_mq_receive()が返す値

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

◆ Enqueue()

template<class T>
nn::nlib::LockFreePriorityQueue< T >::Enqueue ( T *  obj,
int  prio 
)
inlinenoexcept

キューに要素を追加します。スレッドセーフです。

引数
[in]obj要素へのポインタ
[in]prio0以上31以下の優先度
戻り値
nlib_mq_send()が返す値

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

◆ Init()

template<class T>
nn::nlib::LockFreePriorityQueue< T >::Init ( size_t  max_size)
inlinenoexcept

キューを初期化します。スレッドセーフではありません。

引数
[in]max_sizeキューに格納できる要素の最大数
戻り値
0成功した場合
EINVALmax_sizeINT32_MAXを超えている場合
EALREADY既に初期化済みの場合
その他nlib_mq_open()が返すエラー

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


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