Ho un problema in cui sto avendo per creare un'istanza di istanze di oggetti prima di quanto mi piacerebbe farlo perché mi serve per collegare il segnale slot attraverso alcune proprietà profonda, e mi piacerebbe trovare una modo di memorizzare e inoltrare gli slot in modo che io possa costruire oggetti più vicini al loro sito di utilizzo, invece di farlo come variabili membro.Come posso memorizzare e inoltrare gli slot usando boost :: signals2?
Il mio problema di base è che ho un processo che scaricherà un file di aggiornamento su un thread separato e invia un segnale di avanzamento a chiunque sia interessato a . Il segnale è essenzialmente:
typedef boost::signals2::signal<void (double)> DownloadProgress;
supponga che l'implementazione della funzione progress
menzionato sotto conforme a questa; la natura del segnale stesso non è molto importante (sebbene io stia usando per la maggior parte i funtori).
Il segnale viene impostato e il codice si chiama qualcosa di simile:
Updater updater;
updater.onDownloadProgress(&progress);
updater.runDownloadTask();
Quando si chiama updater.runDownloadTask()
, inizierà la UpdaterDownloadTask
, che inizia un HTTPRequest
e restituisce un HTTPResponse
. Il HTTPResponse
è il pezzo che interagisce con il livello di rete e riceve i dati e contiene il segnale DownloadProgress
. Con questo, la mia implementazione sembra un po 'come (bottom-up da HTTPResponse
, pesantemente abbreviato per elidere i metodi che non sono particolarmente illustrativo):
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_;
};
Quindi, la mia Updater deve avere un'istanza di UpdaterDownloadTask
che è sempre intorno, che dispone di un'istanza di HTTPRequest
, che ha un un'istanza di HTTPResponse
-proprio perché devo trasmettere slot connessione dal Updater
(punto di ingresso API pubblica) per HTTPResponse
(dove il segnale frazione).
avrei preferito attuare UpdaterDownloadTask::run()
modo:
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();
}
Ciò avrebbe conseguenze analoghe a livello HTTPRequest (quindi non dover costruire la HTTPResponse finché non eseguire la richiesta) e make complessiva per un flusso di dati migliore con una forte semantica di RAII. Ho precedenza cercato di definire la variabile slots_
come vettore:
std::vector<DownloadProgress::slot_type> slots_;
Eppure posso solo ottenere questo al lavoro se forzo i chiamanti a chiamare onDownloadProgress(boost::ref(slot));
.
Qualcuno ha fatto questo con successo, o ha un buon suggerimento su come memorizzare e inoltrare diverso da quello che sto facendo?
Ho provato alcune cose con un vettore in precedenza, ma potrebbe essere stato un errore da parte mia. Penso tu abbia ragione. –