2017-07-28 1 views
0

現時点では、flex & bisonに基づいて簡単なプログラミング言語を開発しています。長期的に信号を待つ方法は?

私はまず、抽象構文木(AST)を構築し、その評価を続けます。評価の間、ユーザー入力を受信することが可能でなければならない。ユーザの入力はQt-GUIで行われます。 ast-evaluation-procedureは、GUIによって作成されるスレッド・ワーカ・オブジェクトで実行されます。 私の問題:実行中のフレックスを「ブロックする」最良の方法はどちらですか?&バイソンの評価手順は、GUIからユーザー入力を受け取り、その後、手順を実行し続けますか? 残念ながら、評価手順を2つの部分に分割して、GUIからユーザー入力信号を取得し、スロット内の「分割プロシージャ」を続行する方法についてはわかりません。 私の現在の解決策は評価手順内で無限ループで動作します(これは私の意見では貧弱です)。これは、スレッドworker-objectのbooleanメンバー変数(_hasUserInput)がtrueに設定されるまで実行されます。ユーザ入力後、GUIは信号を発する。対応するスロットはスレッドワーカーオブジェクト内にあります。スロットはユーザ入力を受信する。対応するメンバ変数を設定します。さらに、ブール変数はtrueに設定されているため、評価手順の無限ループを放置することができ、ユーザー入力を処理して評価を続けることができます。

機能原理:
GUI - >スレッド(ワーカー・オブジェクト)を開始 - >は、擬似コードにおける長期走行手順

例を開始する:

class ThreadWorker : public QObject { 

    ... 

    // Slot, that reacts to the signal from the GUI 
    void userInput(const QString &input) { 
     _userInput = input; 
     _hasUserInput = true; 
    } 

    // evaluation-procedure 
    void doEvaluation() { 
     // evaluation of the AST 

     ... 

     emit userInputRequired(); 
     while (!hasUserInput){   // Check if user input has been done 
      qApp -> processEvents(); // to react to events 
     } 
     do something with user input; 
     continue valuation;    // Processing of user input and continuation of the procedure 
    } 

    ... 

}; 

私は説明を与えることを試みました私の問題をできるだけ良くし、それがうまくいくことを願っています。より詳しい情報が必要な場合は、お尋ねください。 ご協力いただきありがとうございます!

+0

非ブロックワーカーが必要なのでしょうか? https://stackoverflow.com/questions/32952474/non-blocking-worker-interrupt-file-copyあなたは 'while()'ループを削除し、それをイベント駆動型のものに置き換えます。 – dtech

+0

バイトコードインタープリタがASTベースのものよりも多くの作業が必要なので、いつでも実行を一時停止して再開するのがずっと簡単なので、代わりにそのルートを検討することをお勧めします。 – sepp2k

答えて

0

すでに労働者をQObjectに含めるので、processEvents()に電話する必要はありません。代わりに、AST評価を必要なだけ実行される小さなチャンクに分解してください。私はパブリックインターフェイスをスレッドセーフにしました。したがって、スレッドから直接呼び出すことができます。

// see https://stackoverflow.com/a/40382821/1329652 
bool isSafe(QObject * obj); 
template <typename Class, typename... Args> void postCall(Class * obj, void (Class::*method)(Args...), Args&& ...args); 

class ASTWorker : public QObject { 
    Q_OBJECT 
    QBasicTimer m_evaluateTimer; // a bit lower overhead than QTimer 
    void timerEvent(QTimerEvent * ev) override { 
    if (ev->timerId() == m_evaluateTimer.timerId()) 
     evaluateImpl(); 
    } 
    void evaluateImpl() { 
    bool evaluationDone = {}; 
    QThread::msleep(10); // emulate evaluating a chunk of AST 
    if (!evaluationDone && !m_evaluateTimer.isActive()) 
     m_evaluateTimer.start(0, this); 
    else if (evaluationDone) 
     m_evaluateTimer.stop(); 
    } 
public: 
    using QObject::QObject; 
    /// Thread-safe 
    Q_SLOT void setUserInput(const Data & data) { 
    if (!isSafe(this)) 
     return postCall(this, &ASTWorker::setUserInput, data); 
    QThread::msleep(1); // emulate processing user data 
    } 
    /// Thread-safe 
    Q_SLOT void evaluate() { 
    if (!isSafe(this)) 
     return postCall(this, &ASTWorker::evaluate, data); 
    evaluateImpl(); 
    } 
}; 
関連する問題