2012-01-20 13 views
5

मैं एक समस्या है जहाँ मैं वस्तुओं पहले के उदाहरण का दृष्टांत को की तुलना में मैं ऐसा करने के लिए चाहते हैं, क्योंकि मैं कुछ गहरी स्वामित्व के माध्यम से संकेत कनेक्ट करने के लिए स्लॉट की जरूरत हो रही है, और मैं एक साथ आने के लिए करना चाहते हैं स्लॉट्स को संग्रहीत और अग्रेषित करने के का तरीका ताकि मैं सदस्य चर के रूप में ऐसा करने के बजाय ऑब्जेक्ट्स को अपनी उपयोग साइट पर बना सकूं।बूस्ट :: सिग्नल 2 का उपयोग करके मैं स्लॉट कैसे स्टोर और अग्रेषित कर सकता हूं?

मेरी मूल समस्या यह है कि मेरे पास एक प्रक्रिया है जो फ़ाइल को एक अलग थ्रेड पर अद्यतन डाउनलोड करेगी और रुचि रखने वाले किसी भी व्यक्ति को प्रगति संकेत भेजेंगे। संकेत अनिवार्य है:

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

तो, मेरी Updater है UpdaterDownloadTask है कि का एक उदाहरण के लिए हमेशा के आसपास है, जो HTTPRequest का एक उदाहरण है, जो HTTPResponse -सिर्फ के उदाहरण है क्योंकि मैं स्लॉट HTTPResponse (जहां संकेत अंतर्गत आता है) करने के लिए Updater से कनेक्शन (सार्वजनिक एपीआई प्रवेश बिंदु) को आगे करने के लिए है है।

मैं नहीं बल्कि इसलिए की तरह 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 का निर्माण करने की जरूरत नहीं है ) और समग्र मेकअप मजबूत आरएआईआई अर्थशास्त्र के साथ एक अच्छा डेटा प्रवाह के लिए। मैं पहले से एक वेक्टर के रूप slots_ चर को परिभाषित करने की कोशिश की है:

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

अभी तक मैं केवल इस प्राप्त कर सकते हैं अगर मैं onDownloadProgress(boost::ref(slot)); कॉल करने के लिए कॉल करने के लिए मजबूर काम करने के लिए।

क्या किसी ने इसे सफलतापूर्वक किया है, या स्टोर और आगे क्या करना है इसके अलावा आगे एक अच्छा सुझाव है?

उत्तर

2

मुझे लगता है कि एक वेक्टर में स्लॉट स्टोर करना ठीक काम करना चाहिए।यदि आप boost::ref(...) की आवश्यकता से छुटकारा पाना चाहते हैं तो आप पैरामीटर से & हटा सकते हैं (slot_type कॉपी करने योग्य है)।

वैकल्पिक रूप से, आप HTTPRequest में HTTPResponse आग के अंदर और एक संकेत बारी आग में अपने संकेत हो सकता है, कर रही है, तो आप HTTPRequest में संकेत करने के लिए सभी स्लॉट जुड़ सकता है, तो एक बार HTTPResponse बनाई गई है, तो आप प्रतिक्रिया करने के लिए कनेक्ट सिग्नल onDownloadProgress(request.signalname)। जहां signalname आपका ग्राहक सिग्नल है।

स्यूडोकोड:

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

मुझे आशा है कि मदद करता है।

+0

मैंने पहले एक वेक्टर के साथ कुछ चीजों की कोशिश की थी, लेकिन यह मेरे हिस्से में एक त्रुटि हो सकती है। मुझे लगता है कि आप सही हैं। –

संबंधित मुद्दे