2009-04-19 3 views
9

私はコルーチンをベースとして使用し、おもちゃのスケジューラを実装することに関する非常に基本的なことを知っています。しかし、私は全体として非同期スケジューラについての単純化された見解であると仮定します。私の思考には欠けている穴がたくさんあります。実用的なファイバースケジューラーの実装方法は?

CPUがアイドル/待機中のスケジューラを実行しないようにするにはどうすればよいですか?一部のファイバーはスリープ状態になり、他のファイバーはオペレーティング・システムからの入力を待ちます。

答えて

6

io操作をイベントベースのインターフェイス(選択/ポーリング)に多重化する必要があるため、OSを活用して待機を行いながら、他のファイバのスケジュールを設定することができます。 select/pollにはタイムアウト引数があります。スリープ状態にしたいファイバの場合は、select/pollオプションを使用してスリープコールをエミュレートする優先キューを作成できます。

動作をブロックしているファイバを処理しようとしています(コールの読み書き/スリープなど)。ネイティブスレッドで各ファイバをスケジュールしない限り、直接動作しません - どのような目的を果たします。

実用的な実装については、http://swtch.com/libtask/を参照してください。

+0

libtaskは素晴らしく見えますが、タスクの明示的なユーザースケジューリングを許可していないようです(CPUを特定のタスクに割り当てるAPIが見つかりませんでした)。私はboost :: contextはより一般的に見えると思っています。また、さまざまなタスク間でロックを実装するboost :: fiberというレイヤーがあります – lurscher

0

実装の観点からは、非同期イベントループの実装から開始することができます。次に、非同期イベントハンドラを使用して対応するファイバに切り替えるだけで、ファイバスケジューリングを実装することができます。

スリーピング/ウェイティングファイバは、現在スケジュールされていないことを意味します。代わりにイベントループに切り替えるだけです。

http://svn.cmeerw.net/src/nginetd/trunk/まだ進行中ですが、マルチスレッドイベントループの上にファイバースケジューラを実装しようとしています(Win32 I/O補完ポートまたはLinuxのエッジで起動されるepoll)。

5

おそらく関数のsetcontextファミリ(http://en.wikipedia.org/wiki/Setcontext)を見てください。これは、アプリケーション内で、非同期フォームをブロック(読み込み、書き込み、スリープなど)してスケジューラに戻る可能性のあるすべての関数を再実装する必要があることを意味します。

select()、poll()またはepoll()を使用して完了イベントを待つことになるのは、 "scheduler fiber"だけです。これは、スケジューラがアイドル状態のときに、プロセスがselect/poll/epoll呼び出しでスリープ状態になり、CPUを占有しないことを意味します。

+0

は、どのように、すべてのマシンのスタックに頼ることなく、それをすべての実装に比較setcontextていますか?私は、コルーチンが単純な呼び出しを模倣するために別のコルーチンが停止するまで待つことができます。 – Cheery

1

答えが少し遅れていますが、私はlibevfibersと呼ばれるCでファイバーライブラリの実用的な実装をしています。

若いプロジェクトであるにもかかわらず、プロダクションで使用されます。これは、ソケットの読み書きのような古典的な非同期操作だけでなく、非ブロック的な方法でファイルシステムIOを解決する解決策を提供します。このプロジェクトでは3つの素晴らしいライブラリ--- libcoro、libev、libeioを利用しています。

1

コルーチンを使用して制御フローを制御することもできます。それらの作成をサポートするライブラリはBOOST.ASIOです。

良い例がここにあります:Boost Stackful Coroutines

関連する問題