2012-01-20 12 views
5

Ben bazı derin mülkiyet yoluyla sinyalini yuvaları bağlamak gerekir çünkü bunu yapmak istiyorum daha nesnelerin önceki örneklerini örnekleme yaşıyorum bir sorun var ve bir ile gelip istiyorum yolu, yuvaları saklamak ve iletmek için, üye değişkenleri yerine kullanmak yerine, kullanım sitelerine daha yakın nesneler oluşturabileceğim şekilde.Yuvaları :: signal2'yi kullanarak nasıl depolayabilir ve iletebilirim?

Temel sorunum, numaralı bir güncelleştirmeyi ayrı bir iş parçacığına karşıdan yükleyen bir işlemin olması ve ile ilgilenen herkese bir ilerleme sinyali göndermesidir. sinyal esas olarak:

typedef boost::signals2::signal<void (double)> DownloadProgress; 

progress fonksiyonunun uygulanması Aşağıda bu uygun söz varsayalım; sinyalin doğası çok önemli değil (çoğu zaman için functor kullanıyorum rağmen) çok önemli değil .

sinyal ayarlanır ve kod böyle bir şey denir:

Updater updater; 
updater.onDownloadProgress(&progress); 
updater.runDownloadTask(); 

Eğer updater.runDownloadTask() çağırdığınızda, bir HTTPRequest başlar ve bir HTTPResponse döndürür UpdaterDownloadTask, başlayacaktır. HTTPResponse, ağ katmanı ile etkileşime giren ve verileri alan ve DownloadProgress sinyalini içeren parçadır.

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_; 
}; 

Yani, benim Güncelleyicisi sahiptir

var UpdaterDownloadTask bir örneğini olması: Bununla, benim uygulaması gibi biraz ( HTTPResponse itibaren aşağıdan yukarıya, ağır özellikle açıklayıcı olmayan yöntemler elide için kısaltılır) bakar I (sinyal ait) HTTPResponse için Updater yank bağlantı (genel API giriş noktası) iletmek zorunda çünkü HTTPResponse -just bir örneği vardır HTTPRequest bir örneğini sahip her zaman yaklaşık .

Doğrusu şöyle UpdaterDownloadTask::run() uygulayacağını: Bu HTTPRequest seviyesinde benzer etkileri olacaktır

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(); 
} 

ve genel markasını (bu yüzden isteği gerçekleştirene kadar HTTPResponse inşa etmek gerekmez ) güçlü RAII semantikleri ile daha güzel bir veri akışı için. Ben daha önce bir vektörü olarak slots_ değişken tanımlama denedim:

std::vector<DownloadProgress::slot_type> slots_; 

Oysa ben sadece onDownloadProgress(boost::ref(slot)); aramaya arayanları zorlarsanız çalışmak için bu alabilirsiniz.

Bunu başarılı bir şekilde yapan birileri var mı, yoksa ürününün ne yaptığımdan başka bir yere nasıl iletileceğine dair öneriniz var mı?

cevap

2

Yuvaları bir vektörde saklamanın iyi çalışması gerektiğini düşünüyorum.boost::ref(...) gereksiniminden kurtulmak istiyorsanız, & parametresini onDownloadProgress parametresinden kaldırabilirsiniz (slot_type kopyalanabilir olduğundan).

Alternatif olarak, bunu yaparken, sen HTTPRequest olarak sinyale tüm yuvaları bağlanabilir, HTTPRequest bir sinyal HTTPResponse yangın içinde ve dönüş ateşe sinyali olabilir HTTPResponse oluşturulduktan sonra, o zaman, tepki bağlanmak sinyal onDownloadProgress(request.signalname). signalname'un nerede olduğu müşterinizdir.

yalancı kod:

Request request; 
request.onProgress(myProgressBarCallback); 
    //calls: this.signal.connect(myProgressBarCallback); 
request.go(); 
    //calls: Response response; 
    // and: response.onProgress(this.signal); 

Bunu size yardımcı olmuştur.

+0

Önceden bir vektörle bazı şeyleri denedim, ancak bölümümde bir hata olmuş olabilir. Bence haklısın. –

İlgili konular