ヒント: <task.h>。
は、 CFront の初期バージョンに同梱されていた古い共同マルチタスク ライブラリへの参照です (そのページからダウンロードすることもできます)。
「 A Set of C++ Classes for Co-routine Style Programming 」という論文を読むと、物事がより理にかなっているでしょう。
少し追加:
私は、タスク ライブラリを使用するのに十分な年齢のプログラマではありません。しかし、C++ は、Stroustrup が Simula でタスク ライブラリと同じプロパティの多くを備えたシミュレーションを作成した後に設計されたことを知っているので、常に興味を持っていました。
本の演習を実装する場合、おそらく次のようにします (このコードをテストしたり、コンパイルしようとしたりしていないことに注意してください)。
class Scheduler {
std::list<*ITask> tasks;
public:
void run()
{
while (1) // or at least until some message is sent to stop running
for (std::list<*ITask>::iterator itor = tasks.begin()
, std::list<*ITask>::iterator end = tasks.end()
; itor != end
; ++itor)
(*itor)->run(); // yes, two dereferences
}
void add_task(ITask* task)
{
tasks.push_back(task);
}
};
struct ITask {
virtual ~ITask() { }
virtual void run() = 0;
};
私は、人々が私の選択のいくつかに同意しないことを知っています. たとえば、インターフェイスに構造体を使用します。しかし、構造体には、それらからの継承がデフォルトでパブリックであるという動作があり (クラスからの継承はデフォルトでプライベートです)、インターフェイスからプライベートに継承することに価値がないと思うので、パブリック継承をデフォルトにしないのはなぜですか?
ITask::run() への呼び出しは、タスクが中断できるポイントに到達するまでスケジューラをブロックし、その時点でタスクが run メソッドから戻り、スケジューラが run を再度呼び出すまで待機するという考え方です。継続する。「協調的マルチタスク」の「協調的」とは、「タスクがいつ中断できるかを示す」という意味です (「コルーチン」は通常、「協調的マルチタスク」を意味します)。単純なタスクはその run() メソッドで 1 つのことしか実行できず、より複雑なタスクはステート マシンを実装し、その run() メソッドを使用してオブジェクトの現在の状態を把握し、それに基づいて他のメソッドを呼び出すことができます。その状態で。タスクはこれが機能するためには、ときどきコントロールを手放してください。それが「協調的マルチタスク」の定義だからです。これは、最新のすべてのオペレーティング システムが協調マルチタスクを使用しない理由でもあります。
この実装は、(1) 公平なスケジューリングに従いません (おそらく、タスクの run() メソッドで費やされたクロック ティックの現在の合計を保持し、他のタスクが「追いつく」まで、他のタスクに比べてあまりにも多くの時間を使用したタスクをスキップします)。 、(2)タスクを削除できるようにするか、(3)スケジューラを停止できるようにします。
タスク間の通信に関しては、Plan 9 の libtaskまたはRob Pike の newsqueakを参照してインスピレーションを得ることができます (「Newsqueak の UNIX 実装」のダウンロードには、興味深い仮想マシンでのメッセージ パッシングについて説明している論文「Newsqueak の実装」が含まれています)。
しかし、これはストラウストラップが念頭に置いていた基本的な骨格だと思います。