【发布时间】:2012-01-20 04:43:03
【问题描述】:
我有一个问题,我必须实例化对象的实例 早于我想这样做,因为我需要连接信号 通过一些深刻的所有权插槽,我想想出一种方法 存储和转发插槽,以便我可以更近地构造对象 到他们的使用站点,而不是作为成员变量这样做。
我的基本问题是我有一个下载更新的进程 在单独的线程上提交文件并向任何人发送进度信号 感兴趣的。信号本质上是:
typedef boost::signals2::signal<void (double)> DownloadProgress;
假设提到的progress函数的实现
下面符合这个;信号本身的性质不是很
很重要(尽管我大部分时间都在使用仿函数)。
信号已设置,代码调用如下:
Updater updater;
updater.onDownloadProgress(&progress);
updater.runDownloadTask();
当你调用updater.runDownloadTask()时,它会启动
UpdaterDownloadTask,它开始一个 HTTPRequest 并返回一个
HTTPResponse。 HTTPResponse 是与
网络层并接收数据并包含DownloadProgress
信号。有了这个,我的实现看起来有点像(自下而上
HTTPResponse,严重缩写为省略不属于的方法
特别说明):
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 的实例
总是在身边,它有一个 HTTPRequest 的实例,它有一个
HTTPResponse 的实例——只是因为我必须转发插槽
从 Updater(公共 API 入口点)到 HTTPResponse 的连接
(信号所属的地方)。
我宁愿像这样实现UpdaterDownloadTask::run():
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();
}
这将在 HTTPRequest 级别产生类似的影响(所以我
在我执行请求之前不必构造 HTTPResponse)
总体而言,具有强 RAII 语义的更好的数据流。我有
之前尝试将slots_ 变量定义为向量:
std::vector<DownloadProgress::slot_type> slots_;
然而,如果我强迫呼叫者打电话,我只能让它工作
onDownloadProgress(boost::ref(slot));.
有没有人成功做到这一点,或者有一个很好的建议如何 除了我正在做的事情之外的存储和转发?
【问题讨论】:
标签: c++ boost-signals2