LINUX.ORG.RU

Связь классов из разных потоков

 ,


0

3

Добрый день. Есть проект на Qt. Некий сервер со сбором информации, грубо говоря, подключился к нашему серверу клиент, мы эту информацию должны записать куда-то в БД. Сам объект QTcpServer работает в отдельном потоке (назовем его ObjServer), объект для записи информации о клиентах работает, соответственно, в другом потоке (пусть будет ObjInfo). Как сейчас реализовано взаимодействие этих двух классов:

1. В объект ObjServer передается указатель на объект ObjInfo.

2. Когда нужно записать какую-то информацию о клиенте, то в методе объекта ObjServer вызывает публичный метод объекта ObjInfo.

3. В ранее вызванном методе ObjInfo вызывается InvokeMethod слота объекта ObjInfo, чтобы сама фактическая запись происходила уже в отдельном потоке.

Такой принцип работает, но получается слишком много дублирующего кода. Например, у нас может быть несколько видов информации о клиенте, с разными параметрами и для каждого подобного «чиха» нужно будет городить и публичный метод и слот. Можно, например, вызывать InvokeMethod из объекта ObjServer, но такое решение мне кажется не сильно красивым, что ли. В общем, как-то так, буду благодарен, за любой совет/пинок в нужную сторону. Спасибо.

Отправлять информацию через посылку сигнала, получать в слоте.

Связать сигнал-слот через коннект, указав, что доставлять данные необходимо через очередь сообщений.

Добавить умных указателей для параметров, передаваемых в сигнале - по вкусу.

trex6 ★★★★★ ()

В общем, как-то так, буду благодарен, за любой совет/пинок в нужную сторону.

Например, использовать инструменты, специально предназначенные для обмена информацией между рабочими потоками. Но если нужно обязательно оставаться в рамках Qt, то не вариант, конечно.

eao197 ★★★★★ ()

Эт ты ещё не видел как народ выпендривается на платформах, где нету пользовательской очереди сообщений из коробки...

Сигналы, слоты и queued connection (да и даже тупо auto), это всё как раз для таких случаев.

По поводу дополнительных чихов в интерфейсе - ну используй двойную диспетчеризацию и имей один интерфейсный сигнал и слот, которые получают умный указатель на наследник какого нить Information. Вперёд, изобрети систему заново.

onhydro ()
Ответ на: комментарий от onhydro

Сарказм?) Ну вообще да, одна связка сигнал-слота для каждого типа сообщения будет более понятна при чтении, но с другой стороны, так нужно каждый раз делать новую связку, когда у нас появляется новый тип сообщения. В общем, свои плюсы/минусы есть у обоих способов.

hell_wood ()
Ответ на: комментарий от hell_wood

Ну, кмк, городить какое то околосетевое api, имеет смысл только ради возможности multi/broadcast. Но это настолько редкий случай в бизнесе, что придумать что-то лучше чем модель подписка/оповещение крайне сложно для общего случая.

Иначе - непонятно почему этих акторов столько пиарят на каждой завалящей конфе, но пользуется ими 2.5 человека, включая авторов. А для всего остального есть очереди сообщений(*MQ*).

более понятна при чтении

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

onhydro ()
Ответ на: комментарий от onhydro

этих акторов

По ссылке речь идет не про акторов, а про CSP. Это похожая, но несколько другая штука. Широко используемая и удобная, за примерами в язык Go.

CSP-шные каналы могут быть удобнее сигналов-слотов, во-первых, за счет более низкой связности сущностей (каждая сторона знает только про типы передаваемых данных, но ничего не должна знать друг о друге), и, во-вторых, за счет встроенного механизма back pressure.

Но, если ничего этого в задаче ТС-а не требуется, то в эту сторону можно и не смотреть.

eao197 ★★★★★ ()
Ответ на: комментарий от onhydro

Про акторов просто накипело :)

ИМХО, в конце 2000-х акторы были слишком распиарены на волне хайпа вокруг Erlang-а. И хотя сама по себе это вполне себе хорошая «технология», она достаточно специфическая и явно уместна далеко не всегда. Вот здесь в начале речь идет именно об акторах и их применимости.

eao197 ★★★★★ ()
Ответ на: комментарий от eao197

удобнее сигналов-слотов, во-первых, за счет более низкой связности сущностей (каждая сторона знает только про типы передаваемых данных, но ничего не должна знать друг о друге),

Ну так и сигналы/слоты связываются по сигнатура. Объекты друг про друга ничего не знают.

Back pressure - аргумент.

trex6 ★★★★★ ()
Ответ на: комментарий от trex6

Ну так и сигналы/слоты связываются по сигнатура. Объекты друг про друга ничего не знают.

А как можно сделать connect в Qt, если объекты друг про друга ничего не знают?

eao197 ★★★★★ ()
Ответ на: комментарий от eao197
int main(int argc, char** argv)
{
    QApplication app(argc, argv);
    ClassA objectA;
    ClassB objectB;

    QObject::connect(&objectA, ClassA::signalX, &objectB, ClassB::slotX);
    
    int result = app.exe();

    return result;
}



Классы ClassA и ClassB ничего друг про друга не знают. Параметры signalX и slotX должны совпадать.

trex6 ★★★★★ ()
Последнее исправление: trex6 (всего исправлений: 1)

А по мне норм решение. Для objserver работа с objinfo просто через публичные методы. Другой вопрос: действительно ли нужен второй поток. Неужели производительности не хватит, чтобы оба объекта работали в одном?

rumgot ★★★★★ ()