タスクの再利用

最初から再割り当てを行うよりも、タスク・オブジェクトを再利用するほうが多くの場合効率的です。親は継続、またはプレデセッサーの 1 つとしてよく再利用されます。

注意

オーバーラップの規則: 再利用されるタスク t は、t.execute() の前の呼び出しがまだ実行中の間は t.execute() が再実行される状況で利用してはなりません。ライブラリーのデバッグバージョンは、この規則の違反を検出します。

例えば、t.execute()t を再利用した後に直接作成してはなりません。代わりに、t.execute()t のポインターを返して、t.execute() が完了した後、t が作成されるようにします。

次の表は、このテンプレート・クラスのメンバーの詳細な情報を提供します。
メンバー 説明
void recycle_as_continuation()

要件: execute() メソッドの実行中に呼び出されること。

再利用するタスクの refcount は、n (n は継続タスクのプレデセッサーの数) に設定する必要があります。

注意

呼び出し元は、execute() メソッドがリターンするまでタスクの refcount が 0 にならないことを保証する必要があります。保証できない場合、代わりに recycle_as_safe_continuation() メソッドを使用して、refcountn+1 に設定してください。

次の場合、タスク t で競合状態が発生します。

t.execute()t を継続として再利用する。

継続が t.execute() がリターンする前にすべて完了するプレデセッサーを持っている。

このため、オリジナルの t.execute() の実行中に再利用される t が暗黙的に作成され、オーバーラップの規則に違反してしまいます。

recycle_as_continuation() を使用するパターンは通常、t.execute() が明示的にそのプレデセッサーを作成する代わりにプレデセッサーの 1 つのポインターを返すことにより、競合状態を回避します。スケジューラーは、t.execute() がリターンした後に暗黙的にそのプレデセッサーを作成して、再利用される t が早めに再実行しないことを保証します。

効果: execute() メソッドがリターンしたときに this を破棄しません。

void recycle_as_safe_continuation()

要件: execute() メソッドの実行中に呼び出されること。

再利用するタスクの refcount は、n+1 (n は継続タスクのプレデセッサーの数) に設定する必要があります。+1 は、タスクが再利用されることを表します。

効果: execute() メソッドがリターンしたときに this を破棄しません。

refcount に追加される +1 によって execute() のオリジナルの呼び出しが完了するまで継続が実行されないため、このメソッドは recycle_as_continuation で説明された競合状態を回避します。

void recycle_as_child_of( task& new_successor )

要件: execute() メソッドの実行中に呼び出されること。

効果: thisnew_successor のプレデセッサーとして、execute() メソッドがリターンしたときに破棄しません。