私がドキュメントyield()
機能から理解しているように、制御を別のファイバーに渡しています。D でファイバーの歩留まりを呼び出さないとどうなりますか? スレッドがハングするということですか?
または、繊維がスレッド内で機能し、プロセス内で機能することを間違って理解していますか? そして、プロセスは orthreads
またはfibers
?を持つことができます。
私がドキュメントyield()
機能から理解しているように、制御を別のファイバーに渡しています。D でファイバーの歩留まりを呼び出さないとどうなりますか? スレッドがハングするということですか?
または、繊維がスレッド内で機能し、プロセス内で機能することを間違って理解していますか? そして、プロセスは orthreads
またはfibers
?を持つことができます。
この質問に答えるには、繊維がどのように機能するかを理解することが重要です。メソッドを呼び出すとFiber.call()
、現在の実行コンテキスト (CPU レジスタの状態) がメモリにダンプされ、代わりにそのファイバー オブジェクトの実行コンテキストが読み込まれます。Fiber.yield()
現在の実行コンテキストもダンプされますが、前回現在のファイバーを呼び出した人に制御が渡されます。別のファイバー コンテキストまたはプレーン スレッド コンテキストの両方である可能性があります。実行コンテキストはダンプされたデータによって完全に定義されているため、知る必要はなく、ファイバーに対応している必要さえありません。
ファイバー関数が終了すると、最後に呼び出しがあったかのように、制御を最後の呼び出し元に戻すだけyield
です。主な違いは、ファイバー関数が終了すると、一致するファイバー オブジェクトが「終了」状態になり、降伏すると常に「実行中」状態のままになることです (技術的に実行する必要がなくなった場合でも)。ファイバーをリセットして終了状態でリサイクルする動作は定義されているだけなので、これは重要です。
よくある間違いは、ファイバーをある種のタスクとして扱い、固有のスケジューリング セマンティクスを期待することです。そうではありません-ファイバー自体は、スマートタスクシステムを上に実装するためのコンテキストスイッチングプリミティブにすぎず、独自のスケジューリングはありません。
関連するセマンティクスを示すコード例:
void main ( )
{
import core.thread, std.stdio;
Fiber fiber1, fiber2;
fiber1 = new Fiber({
fiber2.call();
Fiber.yield();
});
fiber2 = new Fiber({
Fiber.yield();
});
fiber1.call(); // switches to fiber1, which switches to fiber2
// which yield back to fiber1 and finally fiber1 yield back to main
assert (fiber1.state == Fiber.State.HOLD && fiber2.state == Fiber.State.HOLD);
fiber2.call(); // switches to fiber2 which reaches end of function
// and switches back to main upon exit
assert (fiber1.state == Fiber.State.HOLD && fiber2.state == Fiber.State.TERM);
fiber1.call(); // switches to fiber1 which also reaches end of function
// and switches back to main upon exist
assert (fiber1.state == Fiber.State.TERM && fiber2.state == Fiber.State.TERM);
}
ファイバー関数が決してyield()
s でない場合、それは協調的ではありません。つまり、実行がその関数に入ると、他のファイバーはその作業を完了しません。