69

GUI ツールキットを使用したことがある場合は、すべてが完了した後に実行する必要があるイベント ループ/メイン ループがあり、アプリケーションを存続させ、さまざまなイベントに応答できることを知っています。たとえば、Qt の場合、main() で次のようにします。

int main() {
    QApplication app(argc, argv);
    // init code
    return app.exec();
}

この場合、 app.exec() はアプリケーションのメインループです。

この種のループを実装する明白な方法は次のとおりです。

void exec() {
    while (1) {
        process_events(); // create a thread for each new event (possibly?)
    }
}

しかし、これは CPU を 100% に制限するため、実際には役に立ちません。では、CPU を完全に消費することなく、応答性の高いイベント ループを実装するにはどうすればよいでしょうか?

回答は、Python および/または C++ で高く評価されます。ありがとう。

脚注: 学習のために、独自のシグナル/スロットを実装し、それらを使用してカスタム イベントを生成します (例: go_forward_event(steps))。しかし、システム イベントを手動で使用する方法を知っている場合は、それについても知りたいです。

4

6 に答える 6

81

私は同じことについて多くの疑問を持っていました!

GUI のメイン ループは、擬似コードで次のようになります。

void App::exec() {
    for(;;) {
        vector<Waitable> waitables;
        waitables.push_back(m_networkSocket);
        waitables.push_back(m_xConnection);
        waitables.push_back(m_globalTimer);
        Waitable* whatHappened = System::waitOnAll(waitables);
        switch(whatHappened) {
            case &m_networkSocket: readAndDispatchNetworkEvent(); break;
            case &m_xConnection: readAndDispatchGuiEvent(); break;
            case &m_globalTimer: readAndDispatchTimerEvent(); break;
        }
    }
}

「待機可能」とは何ですか? まあ、それはシステムに依存します。UNIX では「ファイル記述子」と呼ばれ、「waitOnAll」は ::select システム コールです。いわゆるUNIX 上の でvector<Waitable>あり::fd_set、「whatHappened」は実際には を介し​​て照会されFD_ISSETます。実際の待機可能なハンドルは、さまざまな方法で取得されます。たとえばm_xConnection、::XConnectionNumber() から取得できます。X11 は、このための高レベルで移植可能な API (::XNextEvent()) も提供しますが、それを使用する場合、複数のイベント ソースを同時に待機することはできません。

ブロッキングはどのように機能しますか? 「waitOnAll」は、プロセスを「スリープ リスト」に入れるよう OS に指示するシステムコールです。これは、waitable の 1 つでイベントが発生するまで、CPU 時間が与えられないことを意味します。これは、プロセスがアイドル状態であり、CPU を 0% 消費していることを意味します。イベントが発生すると、プロセスは短時間反応してからアイドル状態に戻ります。GUI アプリは、ほとんどの時間をアイドリングに費やしています

睡眠中のすべての CPU サイクルはどうなりますか? 依存します。場合によっては、別のプロセスがそれらを使用することがあります。そうでない場合、OS は CPU をビジー ループにするか、一時的に低電力モードにします。

詳しくはお尋ねください!

于 2009-03-18T14:29:21.863 に答える
13

ZeroMQ ( http://www.zeromq.org/ )と呼ばれるシンプルで軽量なメッセージング ライブラリを使用します。これはオープン ソース ライブラリ (LGPL) です。これは非常に小さなライブラリです。私のサーバーでは、プロジェクト全体が約 60 秒でコンパイルされます。

ZeroMQ は、イベント駆動型のコードを大幅に簡素化し、パフォーマンスの点で最も効率的なソリューションでもあります。ZeroMQ を使用したスレッド間の通信は、セマフォやローカル UNIX ソケットを使用するよりも (速度の点で) はるかに高速です。ZeroMQ は 100% 移植可能なソリューションでもありますが、他のすべてのソリューションはコードを特定のオペレーティング システムに結び付けます。

于 2009-03-18T16:37:08.420 に答える