Russian Qt Forum

Qt => Общие вопросы => Тема начата: egaz от Март 09, 2012, 12:30



Название: Обоснованность использования QHash
Отправлено: egaz от Март 09, 2012, 12:30
Здравствуйте.
Имеется типичная ситуация:
Из пользовательских данных, оформленных в виде Request,
необходимо сформировать url-запрос, а по пришествии ответа,
обработать его в зависимости от самого Request.

Во многих проектах связь между запросом и ответом устанавливается
посредством QHash, т.е. имеется нечто подобное:

Код:
QNetworkReply Driver::send(Request* request) {
    QUrl url = request->createUrlRequest();
    QNetworkReply reply = networkaccessmanager->get( url );
    requestDataHash.insert ( reply, request );
}

Response Driver::finished(QNetworkReply* reply) {
    Request* request = requestDataHash.value( &reply );
    requestDataHash.remove ( &reply );
    QByteArray replyData = reply->readAll();
    return this->process( replyData , request )
}

Это просто пример, поэтому утечка памяти не в счёт.

Насколько в этом случае целесообразно использовать QHash?
Можно ли обойтись классом контейнером, который хранит Request*
и ловит сигнал finished от конкретного reply:

Код:
QNetworkReply Driver::send(Request* request) {
    QUrl url = request->createUrlRequest();
    Container* container = new Container(request, this);
    QNetworkReply reply = networkaccessmanager->get( url );
    connect(reply, SIGNAL(finished()), container, SLOT(finished());
    requestDataHash.insert ( reply, request );
}

Container::Container(Request* request, Driver* driver) {
    this->request = request;
    this->driver = driver;
}

Container::finished(Request* request, Driver* driver) {
    QByteArray replyData = sender()->readAll();
    driver->process( replyData , request );
    sender()->deleteLater();
}

Здесь можно было ещё ответ от Container оформить в виде сигнала Driver.

Чем черевата такая обёртка, кроме как передачей Driver по указателю?
Если за сеанс посылаются тысячи запросов, то  в первом случае возникает
необоснованная нагрузка на QHash. Возможно, что QSignalMapper позволяет
проще разрулить сигналы и слоты, но надо смотреть в код, на чём он основан.

В реальности не хватает только некоего механизма, где у слота имеется предопределённый параметр:
Цитировать
connect(reply,SIGNAL(finished()),this, SLOT(process(request)));

Буду признателен за обоснованный ответ.


Название: Re: Обоснованность использования QHash
Отправлено: mutineer от Март 09, 2012, 12:38
А зачем вообще хранить запрос? Можно же завязаться на сигнал
void    finished ( QNetworkReply * reply )
и получить запрос из ответа методом QNetworkReply::request()


Название: Re: Обоснованность использования QHash
Отправлено: egaz от Март 09, 2012, 12:46
А зачем вообще хранить запрос? Можно же завязаться на сигнал
void    finished ( QNetworkReply * reply )
и получить запрос из ответа методом QNetworkReply::request()

request - это "низкоуровневый" запрос, даже не всегда соответствующий отправленному (http://qt-project.org/doc/qt-4.8/qnetworkreply.html#request).
Например, запрос фотографии по id. Запросом может быть: http://example.com/XY56Z.png
где XY56Z - это некий хэш системы, не имеющим связи с id фотографии, поэтому
"высокоуровневый" запрос хранит этот id, чтобы при получении ответа сопоставить id и фотографию.


Название: Re: Обоснованность использования QHash
Отправлено: BRE от Март 09, 2012, 12:49
Можно завести отдельную сущность Container, ничего плохого в этом нет, но от хеша избавиться проще воспользовавшись property.
Указатель на Request можно хранить в property объекта QNetworkReply.


Название: Re: Обоснованность использования QHash
Отправлено: mutineer от Март 09, 2012, 12:51
request - это "низкоуровневый" запрос, даже не всегда соответствующий отправленному (http://doc.qt.nokia.com/4.7-snapshot/qnetworkreply.html#request).
Например, запрос фотографии по id. Запросом может быть: http://example.com/XY56Z.png
где XY56Z - это некий хэш системы, не имеющим связи с id фотографии, поэтому
"высокоуровневый" запрос хранит этот id, чтобы при получении ответа сопоставить id и фотографию.

Это догадки или подтверждено документацией/экспериментами?

Судя по этой фразе в доках
Цитировать
QNetworkRequest QNetworkReply::request () const
Returns the request that was posted for this reply. In special, note that the URL for the request may be different than that of the reply
я бы подумал что возаращается именно отправленный запрос

Не нашел фразы "может не соответствовать отправленному", скорее наоборот "может не соответствовать урлу, с которого пришел ответ"


Название: Re: Обоснованность использования QHash
Отправлено: egaz от Март 09, 2012, 13:22
Указатель на Request можно хранить в property объекта QNetworkReply.

Спасибо!

Действительно, получится элегантное решение, но время работы property
будет линейно зависеть от количества этих property у reply, т. к. сделано
это через QMetaObject::indexOfProperty. Поправьте меня, если я не прав.

Т.к. indexOfProperty имеет небольшую оптимизацию, типа name[0] == prop[0],
то остановлюсь пока на ней, чтобы не городить лишнего в модели.

request - это "низкоуровневый" запрос, даже не всегда соответствующий отправленному (http://doc.qt.nokia.com/4.7-snapshot/qnetworkreply.html#request).
Например, запрос фотографии по id. Запросом может быть: http://example.com/XY56Z.png
где XY56Z - это некий хэш системы, не имеющим связи с id фотографии, поэтому
"высокоуровневый" запрос хранит этот id, чтобы при получении ответа сопоставить id и фотографию.

Это догадки или подтверждено документацией/экспериментами?

Если Вы про QNetworkReply::request, то смотрите ниже.
Если же про id фотографии, то это дефакто во многих api.

Не нашел фразы "может не соответствовать отправленному", скорее наоборот "может не соответствовать урлу, с которого пришел ответ"

Я склонен переводить эту фразу, как "URL для запроса может отличаться от находящегося в ответе"
QNetworkReply - это ответ, поэтому QNetworkReply::request() - это и есть находящийся в в ответе URL запроса.


Название: Re: Обоснованность использования QHash
Отправлено: egaz от Март 09, 2012, 13:27
mutineer, поспешу с Вами согласиться.
Действительно, url с которого пришёл ответ, может отличаться от того, который отправляли,
как раз это факт и отображён данной фразе документации.


Название: Re: Обоснованность использования QHash
Отправлено: mutineer от Март 09, 2012, 13:31
mutineer, поспешу с Вами согласиться.
Действительно, url с которого пришёл ответ, может отличаться от того, который отправляли,
как раз это факт и отображён данной фразе документации.

Значит можно предположить что request() возвращает все же исходный запрос. Буду рад, если сможете на практике подтвердить/опровергнуть мою догадку:)


Название: Re: Обоснованность использования QHash
Отправлено: BRE от Март 09, 2012, 14:31
Действительно, получится элегантное решение, но время работы property
будет линейно зависеть от количества этих property у reply, т. к. сделано
это через QMetaObject::indexOfProperty. Поправьте меня, если я не прав.
Мы здесь имеем передачу по сети и тебя так беспокоит время нахождения propery?  ::)
Думаешь когда то это будет узкое место? ;)