boot::signal を調べるという @anno の推奨に従って、検討した結果、可能なオプションのように見えますが、予想どおり、目的の C ソリューションほど単純ではありません。boost::signalのチュートリアルを見て、目前の問題に最も関連する側面を見ていくことにしました。
通知送信者を作成するには:
クライアントがニュース プロバイダーに接続し、情報が到着すると、接続されているすべてのクライアントにニュースを送信する単純なニュース配信サービスを考えてみましょう。ニュース配信サービスは、次のように構築できます。
class NewsItem { /* ... */ };
boost::signal<void (const NewsItem&)> deliverNews;
の目的は、が生成されdeliverNews
たことをオブザーバーに通知することです。NewsItem
オブザーバーは次のように追加できます (boost::bind ライブラリを使用):
ニュースの更新を受信したいクライアントは、ニュース アイテムを受信できる関数オブジェクトを、deliverNews シグナルに接続するだけで済みます。たとえば、アプリケーションにニュース専用の特別なメッセージ領域がある場合があります。たとえば、次のようになります。
struct NewsMessageArea : public MessageArea
{
public:
// ...
void displayNews(const NewsItem& news) const
{
messageText = news.text();
update();
}
};
// ...
NewsMessageArea newsMessageArea = new NewsMessageArea(/* ... */);
// ...
deliverNews.connect(boost::bind(&NewsMessageArea::displayNews, newsMessageArea, _1));
リストから割り当て解除されたオブザーバーを削除する問題に対処するために、boost::signal は次の解決策を提供します。
しかし、ユーザーがニュース メッセージ エリアを閉じて、deliverNews が認識している newsMessageArea オブジェクトを破棄した場合はどうなるでしょうか。ほとんどの場合、セグメンテーション違反が発生します。ただし、Boost.Signals を使用すると、NewsMessageArea を追跡可能にするだけで済み、newsMessageArea が破棄されると、newsMessageArea を含むスロットが切断されます。NewsMessageArea クラスは、boost::signals::trackable クラスから公に派生することによって追跡可能になります。
struct NewsMessageArea : public MessageArea, public boost::signals::trackable
{
// ...
};
現時点では、スロット接続を作成する際の追跡可能オブジェクトの使用には重大な制限があります。Boost.Bind を使用して構築された関数オブジェクトは、boost::bind に渡された追跡可能オブジェクトへのポインターまたは参照が検出され追跡されるように理解されます。