オブジェクトのインスタンスをインスタンス化する必要があるという問題があります。信号を接続する必要があるため、より早くオブジェクトをインスタンス化する必要があります。 スロットを所有しています。私はスロットを格納して転送して、メンバー変数の代わりに に近いオブジェクトを使用サイトに構築できるようにします。boost :: signals2を使ってスロットを格納して転送するにはどうしたらいいですか?
私の基本的な問題は、別のスレッドにアップデート ファイルをダウンロードし、進捗信号を に送信するプロセスがあることです。信号は、本質的に:
typedef boost::signals2::signal<void (double)> DownloadProgress;
はprogress
関数の実装は、以下 これに準拠を述べているものとします。信号そのものの性質はそれほど重要ではありません(私はほとんどの場合、ファンクターを使用していますが)。 重要です。
信号がセットされ、コードは次のようなものと呼ばれている:あなたはupdater.runDownloadTask()
を呼び出すと
Updater updater;
updater.onDownloadProgress(&progress);
updater.runDownloadTask();
、それはHTTPRequest
を開始し、 HTTPResponse
を返す UpdaterDownloadTask
を、開始します。 HTTPResponse
は、 ネットワーク層とやり取りしてデータを受信し、DownloadProgress
信号を含む部分です。この、私の実装は(、 HTTPResponse
からボトムアップ重く、特に説明のない れている方法をElideのと略記)ビットのように見えると:だから
class HTTPResponse
{
public:
// this will be called for every "chunk" the underlying HTTP
// library receives
void processData(const char* data, size_t size)
{
// process the data and then send the progress signal
// assume that currentSize_ and totalSize_ are properly set
progressSignal_(currentSize_ * 100.0/totalSize_);
}
void onDownloadProgress(const DownloadProgress::slot_type& slot)
{
progressSignal_.connect(slot);
}
private:
DownloadProgress progressSignal_;
};
class HTTPRequest
{
public:
HTTPRequest() : response_(new HTTPResponse) { }
void onDownloadProgress(const DownloadProgress::slot_type& slot)
{
response_->connect(slot);
}
boost::shared_ptr<HTTPResponse> perform()
{
// start the request, which operates on response_.
return response_;
}
private:
boost::shared_ptr<HTTPResponse> response_;
};
class UpdaterDownloadTask : public AsyncTask
{
public:
DownloadTask() : request_(new HTTPRequest) { }
void onDownloadProgress(const DownloadProgress::slot_type& slot)
{
request_->connect(slot);
}
void run()
{
// set up the request_ and:
request_>perform();
}
private:
boost::shared_ptr<HTTPRequest> request_;
};
class Updater
{
public:
Updater() : downloadTask_(new UpdaterDownloadTask) { }
void onDownloadProgress(const DownloadProgress::slot_type& slot)
{
downloadTask_->onDownloadProgress(slot);
}
void runDownloadTask() { downloadTask_.submit() }
private:
boost::shared_ptr<UpdaterDownloadTask> downloadTask_;
};
、私のアップデータですUpdaterDownloadTask
のインスタンスを持つことがあります 常に周りに、私は(信号が所属)HTTPResponse
にUpdater
からスロット 接続(パブリックAPIエントリポイント)を転送する必要があるためHTTPResponse
-JUSTの インスタンスを有するHTTPRequest
のインスタンスを有します。
私はむしろそうのようなUpdaterDownloadTask::run()
を実装します:これは、HTTPRequestのレベルでの同様の意味合いを持っているでしょう
void run()
{
HTTPRequest request;
request.onDownloadProgress(slots_);
#if 0
// The above is more or less equivalent to
BOOST_FOREACH(const DownloadProgress::slot_type& slot, slots_)
{
request.onDownloadProgress(slot);
}
#endif
request.perform();
}
と全体的なメイクを(ので、私は、要求を実行するまでHTTPResponseはを構築する必要はありません )強力なRAIIセマンティクスを持つより良いデータフローを実現します。私は は以前にベクトルとしてslots_
変数を定義しようとしました:
std::vector<DownloadProgress::slot_type> slots_;
をしかし、私は onDownloadProgress(boost::ref(slot));
を呼び出すために発信者を強制する場合、私はこれだけ仕事を得ることができます。
誰でもこれをうまくやったことがありますか、または私がやっていること以外に保存して転送する方法については、良い提案がありますか?
以前はベクターで試したことがありましたが、私のところはエラーだったかもしれません。あなたが正しいと思います。 –