2012-01-20 28 views
5

Tôi gặp sự cố khi tôi phải khởi tạo phiên bản đối tượng sớm hơn tôi muốn làm như vậy vì tôi cần kết nối tín hiệu vị trí thông qua một số quyền sở hữu sâu và tôi muốn tìm ra cách lưu trữ và chuyển tiếp các vị trí để tôi có thể xây dựng các đối tượng gần hơn đến trang web sử dụng của chúng, thay vì làm như vậy dưới dạng biến thành viên.Làm cách nào để lưu trữ và chuyển tiếp các vị trí bằng cách sử dụng tăng :: signal2?

Vấn đề cơ bản của tôi là tôi có một quá trình sẽ tải xuống bản cập nhật tệp trên một chuỗi riêng biệt và gửi tín hiệu tiến độ cho bất kỳ ai là quan tâm. Các tín hiệu về cơ bản là:

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

Giả định rằng việc thực hiện các chức năng progress nêu dưới đây phù hợp với này; bản chất của tín hiệu chính nó không phải là rất quan trọng (mặc dù tôi đang sử dụng functors cho hầu hết các phần).

Các tín hiệu được thiết lập và mã được gọi là một cái gì đó như thế này:

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

Khi bạn gọi updater.runDownloadTask(), nó sẽ bắt đầu UpdaterDownloadTask, bắt đầu một HTTPRequest và trả về một HTTPResponse. HTTPResponse là phần tương tác với lớp mạng và nhận dữ liệu và chứa tín hiệu DownloadProgress . Với điều này, thực hiện của tôi trông hơi giống (từ dưới lên từ HTTPResponse, nặng nề viết tắt là bõ mẫu âm chót phương pháp mà không phải là đặc biệt là minh họa):

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

Vì vậy, Updater tôi phải có một thể hiện của UpdaterDownloadTask đó là luôn xung quanh, trong đó có một thể hiện của HTTPRequest, trong đó có một trường hợp của HTTPResponse -Cũng vì tôi phải chuyển khe kết nối từ Updater (API công cộng entry point) để HTTPResponse (nơi các tín hiệu thuộc).

Tôi thà thực hiện UpdaterDownloadTask::run() như vậy:

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

Điều này sẽ có tác động tương tự ở cấp HttpRequest (vì vậy tôi không cần phải xây dựng các HttpResponse cho đến khi tôi thực hiện theo yêu cầu) và làm cho tổng thể cho một luồng dữ liệu đẹp hơn với ngữ nghĩa RAII mạnh mẽ. Tôi đã trước đó cố gắng xác định các biến slots_ như một vector:

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

Tuy nhiên, tôi chỉ có thể có được điều này để làm việc nếu tôi buộc người gọi phải gọi onDownloadProgress(boost::ref(slot));.

Có ai đã làm điều này thành công hay có đề xuất tốt về cách lưu trữ và chuyển tiếp khác với những gì tôi đang làm không?

Trả lời

2

Tôi nghĩ việc lưu trữ các vị trí trong một véc-tơ sẽ hoạt động tốt.Nếu bạn muốn loại bỏ nhu cầu cho boost::ref(...), bạn có thể xóa số & khỏi thông số onDownloadProgress (vì slot_type có thể sao chép được).

Ngoài ra, bạn có thể có tín hiệu của bạn bên HTTPResponse lửa và lần lượt lửa một tín hiệu trong HTTPRequest, làm điều đó, bạn có thể kết nối tất cả các khe để các tín hiệu trong HTTPRequest, sau đó một lần HTTPResponse được tạo ra, bạn kết nối với các phản ứng tín hiệu onDownloadProgress(request.signalname). Trường hợp signalname là tín hiệu khách hàng của bạn.

giả:

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

Tôi hy vọng rằng sẽ giúp.

+0

Tôi đã thử một số thứ với một véc tơ trước đó, nhưng có thể do lỗi của tôi. Tôi nghĩ bạn đúng. –

Các vấn đề liên quan