Russian Qt Forum
Сентябрь 30, 2024, 16:33 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Обоснованность использования QHash  (Прочитано 4771 раз)
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)));

Буду признателен за обоснованный ответ.
Записан
mutineer
Гость
« Ответ #1 : Март 09, 2012, 12:38 »

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

А зачем вообще хранить запрос? Можно же завязаться на сигнал
void    finished ( QNetworkReply * reply )
и получить запрос из ответа методом QNetworkReply::request()

request - это "низкоуровневый" запрос, даже не всегда соответствующий отправленному.
Например, запрос фотографии по id. Запросом может быть: http://example.com/XY56Z.png
где XY56Z - это некий хэш системы, не имеющим связи с id фотографии, поэтому
"высокоуровневый" запрос хранит этот id, чтобы при получении ответа сопоставить id и фотографию.
« Последнее редактирование: Март 09, 2012, 12:50 от egaz » Записан
BRE
Гость
« Ответ #3 : Март 09, 2012, 12:49 »

Можно завести отдельную сущность Container, ничего плохого в этом нет, но от хеша избавиться проще воспользовавшись property.
Указатель на Request можно хранить в property объекта QNetworkReply.
Записан
mutineer
Гость
« Ответ #4 : Март 09, 2012, 12:51 »

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
я бы подумал что возаращается именно отправленный запрос

Не нашел фразы "может не соответствовать отправленному", скорее наоборот "может не соответствовать урлу, с которого пришел ответ"
« Последнее редактирование: Март 09, 2012, 12:52 от mutineer » Записан
egaz
Гость
« Ответ #5 : Март 09, 2012, 13:22 »

Указатель на Request можно хранить в property объекта QNetworkReply.

Спасибо!

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

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

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

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

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

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

Я склонен переводить эту фразу, как "URL для запроса может отличаться от находящегося в ответе"
QNetworkReply - это ответ, поэтому QNetworkReply::request() - это и есть находящийся в в ответе URL запроса.
Записан
egaz
Гость
« Ответ #6 : Март 09, 2012, 13:27 »

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

mutineer, поспешу с Вами согласиться.
Действительно, url с которого пришёл ответ, может отличаться от того, который отправляли,
как раз это факт и отображён данной фразе документации.

Значит можно предположить что request() возвращает все же исходный запрос. Буду рад, если сможете на практике подтвердить/опровергнуть мою догадку:)
Записан
BRE
Гость
« Ответ #8 : Март 09, 2012, 14:31 »

Действительно, получится элегантное решение, но время работы property
будет линейно зависеть от количества этих property у reply, т. к. сделано
это через QMetaObject::indexOfProperty. Поправьте меня, если я не прав.
Мы здесь имеем передачу по сети и тебя так беспокоит время нахождения propery?  Строит глазки
Думаешь когда то это будет узкое место? Подмигивающий
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.073 секунд. Запросов: 21.