問題タブ [boost-signals2]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - boost::signals2 を使用してスロットを保存および転送するにはどうすればよいですか?
深い所有権を介してシグナルスロットを接続する必要があるため、オブジェクトのインスタンスを希望するよりも早くインスタンス化する必要があるという問題があります。これにより、メンバー変数としてではなく、使用場所に近いオブジェクトを構築できます。
私の基本的な問題は、別のスレッドで更新ファイルをダウンロードし、興味のある人に進行状況信号を送信するプロセスがあることです。信号は本質的に次のとおりです。
以下の関数の実装はprogress
これに従うものとします。シグナル自体の性質はそれほど重要ではありません (ただし、ほとんどの部分でファンクターを使用しています)。
シグナルが設定され、コードは次のように呼び出されます。
を呼び出すとupdater.runDownloadTask()
、 が開始され
UpdaterDownloadTask
、 が開始されて がHTTPRequest
返されます
HTTPResponse
。はHTTPResponse
、ネットワーク層とやり取りし、データを受信してDownloadProgress
信号を含む部分です。これにより、私の実装は少し似ています ( のボトムアップ、
HTTPResponse
特に説明にならないメソッドを削除するために大幅に省略されています):
そのため、私のアップデーターには、UpdaterDownloadTask
常に存在する のインスタンスが必要ですHTTPRequest
。これには のインスタンスがあり、 のインスタンスがあります。これはHTTPResponse
、スロット接続をUpdater
(パブリック API エントリ ポイント) からHTTPResponse
(信号が属する場所) に転送する必要があるためです。 .
私はむしろUpdaterDownloadTask::run()
次のように実装したいと思います:
これは、HTTPRequest レベルで同様の意味を持ち (したがって、リクエストを実行するまで HTTPResponse を構築する必要はありません)、全体的に強力な RAII セマンティクスを備えたより優れたデータ フローを実現します。私は以前、slots_
変数をベクトルとして定義しようとしました:
それでも、発信者に強制的に
onDownloadProgress(boost::ref(slot));
.
誰かがこれを成功させましたか、または私がしていること以外に保存および転送する方法について良い提案がありますか?
c++ - boost::signals2 シグナルの呼び出しをシリアル化する既存の方法はありますか?
オブジェクトからの状態変化に関する通知が明確に定義された順序でスロットに到達するようにするために、boost::signals2 シグナルのマルチスレッド呼び出しをシリアル化したいと考えています。
バックグラウンド
マルチスレッド プログラムに内部状態を持つオブジェクトがあります。内部状態の一部はプログラムの他の部分にとって興味深いものであり、オブジェクトは次のような boost::signals2 シグナルを使用して状態の変化を公開します。
問題
OnEvent ハンドラーの同時呼び出しが複数ある場合、実際に変更が行われた順序とは別の順序で状態の変更がリスナーに通知される可能性があります。状態自体は上記のようなミューテックスによって保護されているため、実際の状態は明確に定義されています。ただし、デッドロックが発生する可能性があるため、シグナルの呼び出し全体でミューテックスを保持することはできません。これは、シグナルの実際の呼び出しが任意の順序で発生する可能性があることを意味しますが、状態の変化が実際に発生したのと同じ順序で呼び出す必要があります。
この問題を処理する 1 つの方法は、状態をシグナルから削除し、状態が変化したことをリスナーに通知することです。その後、オブジェクトの状態を照会し、信号が発生したときのオブジェクトの状態またはそれ以降の状態を取得します。私のシナリオでは、リスナーはすべての状態変更について通知を受ける必要があるため、この方法はここでは機能しません。
私の次のアプローチは、次のようなものになります。
私は上記のコードを試していないので、バグやコンパイル エラーが散らばっている可能性がありますが、私が求めているものを推測できるはずです。私の直感によると、この種の問題に遭遇したのは私が初めてではなく、試行錯誤したコードを自分で使用することを好みます... :) だから私の質問は本当に:
boost::signals2 シグナルのシリアル化された呼び出しを実現する既存の方法はありますか (signals2 ライブラリや一般的なパターンに組み込まれているなど)?
c++ - boost::signals2 スロットは非静的関数メンバーですか?
最近、学習目的で遊んでいて、クラス内にある非静的boost::signals2
スロットに信号を接続できるかどうか疑問に思っていました(Qt のように)。次の点を考慮してください。
Controller::print
ここで、非静的メンバーを作成したいと思います。boost::thread
たとえば、これは ; を使用して実現できますboost::bind
。これを行う方法はありますboost::signals2
か?
c++ - Boost.Signals2破壊の安全性
オブジェクト 1 に Boost.Signals2 信号があり、オブジェクト 2 に接続します。
オブジェクト 2 が破壊された場合、信号は切断されず、信号が送信されたときに問題が発生する可能性があります。
これを解決するためにscoped_connection
、オブジェクト 2 を保持します。問題は、オブジェクト 1 がシグナルで破壊され、次にオブジェクト 2 が破壊された場合です。
それは問題を引き起こしますか?一般的な問題を解決するためのより良い方法はありますか? (オブジェクト 1 -> オブジェクト 2 からの接続があり、そのうちの 1 つが破棄されると切断されます)。
問題を示すコード:
これは安全ですか?
c++ - boost :: signalを使用してオブザーバーパターンを実装するにはどうすればよいですか?
私は多くのリンクされたオブジェクトで構成されるアプリケーションを持っています。それぞれのオブジェクトには、機能するために必要なパラメーターがあります。私はコンテキストパターンを使用しているので、各オブジェクトは、構築時に与えられるコンテキストオブジェクト参照に従って独自のパラメーターを設定します。これは、以下に示す簡略化されたコード例でうまく機能します。
私が追加しようとしている次の機能はオブザーバーパターンです。これにより、コンテキストオブジェクトのパラメーターが変更されると、各サブスクライバーオブジェクトに通知され、それに応じてパラメーターが更新されます。ただし、信号をスロットに接続するために使用する必要のある構文を理解するのに問題があります。
理想的には、サブスクライバーオブジェクトを構築時にパラメータークラスに登録して、オブジェクトの存続期間中更新できるようにします(つまり、破棄時に登録を解除する必要があります。さらに、何らかのRAII手法を使用する必要があります。範囲外になった場合は登録を解除します)。以下は、私が可能な限り単純に要約したコード例です。
出力は現在です
処理装置0param= 1
処理装置1param= 2
処理装置0param= 1
処理装置1param= 2
目標はそれを実現することです...
処理装置0param= 1
処理装置1param= 2
処理装置0param= 11
処理装置1パラメーター=22
私が現在使用しているコードは以下のとおりです。試してみたい場合は、現在の形式で問題なくコンパイルされます。信号をスロットに接続するために必要な変更を提案してください。将来的に問題を引き起こす可能性のある設計上の問題もお気軽に指摘してください。前もって感謝します。
c++ - エラー: 「クラス 'boost::signals2::scoped_connection' で宣言されたプライベート メンバーにアクセスできません」?
// .cpp
AddEventOccurredObserver
(に委任しboost::signals2::connect()
て返すことに注意してくださいboost::signals2::connection
)
次のエラーが表示されます。テンプレートのエラーを解釈するのは難しいですが、エラーはのメンバー宣言で発生しているようですstd::vector<boost::signals2::scoped_connection> boostSignalConnections_;
検索しましたが、scoped_connection がコピーできないことに関係していると思いますか? わからない。私が scoped_connection を使用している理由は、この SO の質問のためです: 多くの信号/スロットの接続/切断を boost:: signals2 で処理する
アップデート
参考までに、 から に変更scoped_connection
するconnection
と動作します: std::vector<boost::signals2::connection> boostSignalConnections_;
. 使用する私の全体的な理由scoped_connection
は、それらが破壊時に自動的に接続を切断することですが、私はそうでconnection
はないと信じています。ただし、コレクションを繰り返し処理して、それぞれを手動で切断することはできます。
c++ - 複数のスレッドを使用するQtアプリケーションでブースト信号を処理する
次の問題があります。メインアプリケーションは、ウィンドウとユーザーインタラクションを表示するためにQtツールキットを使用しています。ただし、アプリケーションの大部分はGUI部分を認識していません。次のデザインを作成しました。
- 特定のオブジェクトのレンダリングを要求する可能性のあるシングルトンクラスがあります(OpenSceneGraphノード。ただし、これは質問には関係ありません)。
- レンダリング要求により、シングルトンは信号を送信します
- メインウィンドウクラス(Qtを使用)には、オブジェクトのレンダリングを処理するためのスロットがあります
- 現在、スロットは新しいテキスト編集ウィジェットを作成し、それを
QMdiArea
メインウィンドウのに配置するだけです。
ただし、新しいウィジェットを作成しようとすると、必然的にアプリケーションがクラッシュします。エラーメッセージ領域:
スタックオーバーフローを熟読した後、私は同様の質問を見つけました(これはこの状況にはすぐには当てはまりませんでした)。明らかに、メインウィンドウの何かを別のスレッドから変更するとき、Qtはそれを気に入らない。しかし、私は意識的に新しいスレッドを作成しなかったので、シングルトン(の呼び出しの直後にmain関数で作成されるQApplication()
)はQtと同じスレッドにあるべきだと思いました。どうやら、私は間違っています。
これは私が行っていることを示す最小限の例です(コードの関連部分を抽出したので、例は正確には機能しません):
この問題を解決するための私の試みは非常に不器用でした:
- ブーストシグナルと同じシグネチャを持つクラスで新しいQtシグナルを作成しました
MainWindow
- ブースト信号を処理するスロットで、新しい
Qt
信号を出力し、ポインターを渡します - ポインタを受け取る新しいQtスロットを作成しました
新しいスロットで新しいウィンドウを開くと、すべてが機能します。しかし、これは非常に不器用だと思います。そのようなすべてのブースト信号をカスケードする必要がありますか、それともより良い方法がありますか?
c++ - Glib :: DispatcherをシミュレートするためのBoost機能はありますか?
私は現在、中規模のソフトウェアプロジェクトをリファクタリングしているところです。これには、複数のスレッドで使用される中央のカーネルのようなクラスが含まれています。現在、このクラスは、Glib::Dispatcher
複数のスレッドによって発行されるシグナルを処理するためにを使用します。glibmm
リファクタリングプロセスの1つの目標は、 (新しいフレームワークとして使用されるため)完全に取り除くことであるため、をQt
使用してディスパッチャ機能を「シミュレート」する方法を見つけようとしていBoost
ます。Boost.Signals
私はすでにとを調べましBoost.Signals2
たが、これらのライブラリのどちらもディスパッチャに代わるものを提供していないようです。
コーディネーターが何をすべきかを明確にするために、公式ドキュメントからの簡単な説明を次に示します。
Glib::Dispatcherはsigc::signalと同様に機能します。ただし、通常の信号とは異なり、通知はパイプを介して非同期で行われます。これは、スレッド間で通信するためのシンプルで効率的な方法であり、単一のGUIスレッドを持つスレッドモデルで特に役立ちます。
オペレーティングシステムの内部I/Oロックを除いて、ミューテックスロックは含まれていません。これは、いくつかの使用規則を意味します。
- シグナルに接続して通知を受信できるスレッドは1つだけですが、ロックしなくても複数の送信者が許可されます。
- GLibメインループは受信スレッドで実行する必要があります(これは通常GUIスレッドになります)。
- Dispatcherオブジェクトは、レシーバースレッドによってインスタンス化される必要があります。
- 余分なロックを回避したい場合は、送信側スレッドを作成する前にDispatcherオブジェクトをインスタンス化する必要があります。
- Dispatcherオブジェクトは、レシーバースレッドによって削除される必要があります。
- 同じレシーバースレッドによってインスタンス化されるすべてのDispatcherオブジェクトは、同じメインコンテキストを使用する必要があります。
正しい方向への指針を教えていただけますか?これは私が使用して達成できる種類の機能Boost.Signals
ですかBoost.Signals2
?
編集:コメンターが正しく指摘したように、使用Qt
することはおそらくオプションでしょう。ただし、リファクタリングしているクラスは非常に低レベルであるため、この追加の依存関係を追加したくありません。
c++ - boost::signals2 信号をマップに保存しますか?
次の問題に直面しています:多数の シグナル変数をマップに保存したいです。boost::signals2
これらの信号はコピー不可であるため、これは明らかに機能しません。どうすればこれを回避できますか? 私はすでにこの古い質問を見つけました。その中で、ポスターは信号を として保存することを提案していshared_ptr
ます。これが唯一の方法ですか?欠点はありますか、それとももっと重要なことですが、安全ですか?
c++ - ブースト信号の代替デフォルトの指定2
Boost の signal2 ライブラリは、その拡張機能の一部について代替パラメータを渡すための優れた方法を定義しています (そのパラメータ ライブラリを介して)。これらの代替パラメーターの 1 つが私のコードでかなり一般的である場合、使用をさらに簡素化するヘルパーを作成したいと思います。たとえば、別のミューテックス タイプを指定するには、次のようにします。
残念ながら、これを行うことで、冗長な構文に戻ったり、 my_signal_with_combiner などの追加のメタ関数を定義したりすることなく、他のシグナルパラメーター (コンバイナータイプなど) の代替値を指定する機能も「失って」しまいました (これはばかげているようです)。 . コンバイナーのデフォルトでは、戻り値の型を取得するために署名を分解する必要があるため、デフォルトのテンプレートパラメーター値でもそれを行うことはできないと思います。(もちろん、理想的には、コンバイナーだけでなく、他のパラメーターのいずれかで機能するものが欲しいです。)
したがって、「本当の」質問は次のとおりです。それと同じように動作するが、パラメーターの1つに異なるデフォルト値を持つsignal_typeのようなものを定義する(簡単な)方法はありますか?(理想的には、Boost.Signals2 が将来さらにパラメーターを追加する場合、変更する必要はありません。)
(また、C++11 は使用しないでください。まだ古いコンパイラを使用しています。)