方法: 手動キューのディスパッチを管理するためにイベントを使用する
例
ゲームでは、タスク キューに使用するスレッドを、ゲーム内の他の処理と共有する必要がある場合があります。 次の例は、タスクキューを使用して、ディスパッチするアイテムがある場合に条件変数に通知する方法を示しています。
// We use condition variables to signal when there's something for us
// in the queue and a bool to signal when we want the whole thing to close.
// Keep all this in a struct for convenient access.
struct QueueControl
{
std::condition_variable workActivity;
std::mutex workMutex;
std::condition_variable completionActivity;
std::mutex completionMutex;
bool terminate = false;
} queueControl;
void CALLBACK TaskQueueNewItemSubmitted(
void* context, XTaskQueueHandle, XTaskQueuePort port)
{
// A new callback has been submitted. Notify the correct condition variable.
QueueControl* queueControl = static_cast<QueueControl*>(context);
switch (port)
{
case XTaskQueuePort::Work:
queueControl->workActivity.notify_all();
break;
case XTaskQueuePort::Completion:
queueControl->completionActivity.notify_all();
break;
}
}
void CreatingTaskQueueWithManualSignaling()
{
// Create a manual task queue.
XTaskQueueHandle queue;
HRESULT hr = XTaskQueueCreate(
XTaskQueueDispatchMode::Manual,
XTaskQueueDispatchMode::Manual,
&queue);
if (FAILED(hr))
{
printf("Creating queue failed: 0x%x\r\n", hr);
return;
}
// Listen to callback-submitted notifications to signal
// our condition variable.
XTaskQueueRegistrationToken token;
hr = XTaskQueueRegisterMonitor(
queue, &queueControl,
TaskQueueNewItemSubmitted, &token);
std::thread workThread([&]()
{
std::unique_lock<std::mutex> lock(queueControl.workMutex);
while (!queueControl.terminate)
{
queueControl.workActivity.wait(lock);
XTaskQueueDispatch(queue, XTaskQueuePort::Work, 0);
}
});
std::thread completionThread([&]()
{
std::unique_lock<std::mutex> lock(queueControl.completionMutex);
while (!queueControl.terminate)
{
queueControl.completionActivity.wait(lock);
XTaskQueueDispatch(queue, XTaskQueuePort::Completion, 0);
}
});
SubmitCallbacks(queue);
// Wait a while for the callbacks to run.
Sleep(1000);
XTaskQueueTerminate(queue, true, nullptr, nullptr);
queueControl.terminate = true;
queueControl.workActivity.notify_all();
queueControl.completionActivity.notify_all();
workThread.join();
completionThread.join();
}