Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [Qt] Удаление объекта, "каша малаша" :) 
:(
    Опции темы
chaos
Дата 22.10.2009, 12:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Серийный программист
****


Профиль
Группа: Завсегдатай
Сообщений: 2979
Регистрация: 7.7.2004
Где: Екатеринбург

Репутация: 5
Всего: 44



Дорого времени суток!
стало интересна следующая задача:

есть Event
Код

class MyEvent : public QEvent 
{
public:
    .......
    virtual ~MyEvent() {}

    void dispatch()
    {
        QApplication::postEvent(FrontConteroller::instance(), this);
    }
}


есть такая штука
Код

bool FrontController::event(QEvent *evt)
{
    const QString cmdName = commandsMap[evt->type()];
    ICommand *cmd = (ICommand*)QMetaType::construct(cmdName);
    //Создаем бизнес делегата
    //в кманду инжектируем делегата, а в делегата команду
    cmd->execute((MyEvent*)evt);
}


команда
Код

void FooCommand::execute(MyEvent* event)
{
    AuthEvent *evt = (AuthEvent*)event;
    ((IAuthDelegate*)businessDelegate)->login(evt->userName(), event->password());
}

void FooCommand::fail()
{
    QMessageBox.....
}

void FooCommand::result()
{
    QMessageBox.....
}


делегат
Код

void AuthDelegate::login(const QString& userName, const QString& password)
{
    AsyncToken *token = service->login(userName, password);
    token->addResponder(responder);
}


токен
Код

void AsynkToken::addResponder(IResponder *responder)
{
    connect(this, SIGNAL(fail()), responder, SLOT(fail());
    connect(this, SIGNAL(result()), responder, SLOT(result());
}


вот. Команда значит реализует интерфейс респондера. Сервис пускай реализует AsyncToken.

вообщем получилась такая "каша" посылается конкретынй ивент, по типу ивента создаем команду, бизнес делегата для конкретной команды запускаем ее.через делегат обращаемся к сервису, вызывая конкретную функцию(асинхронно), тот нам в свою очередь "бумажку, мол распишитесь" smile по результату выполнения конкретной функции сервиса пошлются в зависимости от ситуации 2 сигнала: результат(для просто ты опустил) выполнения или ошибка. те в команде вызовится оди из двух слотов.

Вопрос: как лучше убить команду после выполнения слота?

Добавлено @ 12:54
Самый прсото способ удалять команду в слотах, те в самом конце выполнения оных, но не хочу про это постоянно помнить.

Это сообщение отредактировал(а) chaos - 22.10.2009, 20:03
PM WWW   Вверх
SABROG
Дата 23.10.2009, 07:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 81
Всего: 91



Цитата(chaos @  22.10.2009,  12:52 Найти цитируемый пост)
Код
(ICommand*)QMetaType::construct(cmdName);

Судя по документации в функцию construct передается параметр типа int, а не QString.


Цитата(chaos @  22.10.2009,  12:52 Найти цитируемый пост)
Код
->login(evt->userName(), event->password())


Здесь, возможно, опечатка из-за того, что ты уже сам запутался где у тебя чего: evt->userName() и event->password()


Цитата(chaos @  22.10.2009,  12:52 Найти цитируемый пост)
AsyncToken *token
void AsynkToken::addResponder(IResponder *responder)


Тоже опечатка. Судя по всему это не рабочий код. Пытаясь вникнуть в тему и просидя за твоим постом 10 минут внимательно вчитываясь я пришел к выводу, что вопрос можно было сформировать так:

Здесь создается копия зарегистрированного объекта пользовательского типа:

Код

ICommand *cmd = (ICommand*)QMetaType::construct(cmdName);


Что-то типа new ICommand; Т.к. тип не на базе QObject'a и экземпляр класса должен жить в момент выполнения цикла событий, т.к. происходит асинхронная работа, то удалять его в конце метода event() нельзя, а надо, чтобы он удалился сам, когда станет не нужным, методом deleteLater() воспользоваться не удастся. Вариант удалять в конце метода не приемлем, т.к. не хочется помнить об этом и т.д.

Тогда варианты такие: объект класса QEvent удаляется сам. Параметры можно передавать как через сигналы, так и через эвенты. Т.е. вариант отказаться от своего пользовательского типа или сделать его на базе QObject. 

Еще можно попробовать заменить QApplication::postEvent на QApplication::sendEvent, дождаться выполнения и удалить экземпляр команды, соотнося его с каким-то конкретным эвентом.


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
chaos
Дата 23.10.2009, 09:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Серийный программист
****


Профиль
Группа: Завсегдатай
Сообщений: 2979
Регистрация: 7.7.2004
Где: Екатеринбург

Репутация: 5
Всего: 44



Цитата(SABROG @ 23.10.2009,  04:58)
Цитата(chaos @  22.10.2009,  12:52 Найти цитируемый пост)
Код
(ICommand*)QMetaType::construct(cmdName);

Судя по документации в функцию construct передается параметр типа int, а не QString.


Цитата(chaos @  22.10.2009,  12:52 Найти цитируемый пост)
Код
->login(evt->userName(), event->password())


Здесь, возможно, опечатка из-за того, что ты уже сам запутался где у тебя чего: evt->userName() и event->password()


Цитата(chaos @  22.10.2009,  12:52 Найти цитируемый пост)
AsyncToken *token
void AsynkToken::addResponder(IResponder *responder)


Тоже опечатка. Судя по всему это не рабочий код. Пытаясь вникнуть в тему и просидя за твоим постом 10 минут внимательно вчитываясь я пришел к выводу, что вопрос можно было сформировать так:

Здесь создается копия зарегистрированного объекта пользовательского типа:

Код

ICommand *cmd = (ICommand*)QMetaType::construct(cmdName);


Что-то типа new ICommand; Т.к. тип не на базе QObject'a и экземпляр класса должен жить в момент выполнения цикла событий, т.к. происходит асинхронная работа, то удалять его в конце метода event() нельзя, а надо, чтобы он удалился сам, когда станет не нужным, методом deleteLater() воспользоваться не удастся. Вариант удалять в конце метода не приемлем, т.к. не хочется помнить об этом и т.д.

Тогда варианты такие: объект класса QEvent удаляется сам. Параметры можно передавать как через сигналы, так и через эвенты. Т.е. вариант отказаться от своего пользовательского типа или сделать его на базе QObject. 

Еще можно попробовать заменить QApplication::postEvent на QApplication::sendEvent, дождаться выполнения и удалить экземпляр команды, соотнося его с каким-то конкретным эвентом.

1. оцепятка так скаже smile
Код

QMetaType::construct(QMetaType::type(cmdName));


2. Ага, тоже опечатка. evt должно быть

3. опечатки вроде нет smile Async сокращенно от Asynchronously

4. код ага, не рабочий. это так сказать мысли только

5. По классу команда. щас я его пока вижу таким
Код

struct ICommand
{
    virtual void execute(Event *event) = 0;
}

class Responder : QObject
{
Q_OBJECT
public slots:
    virtual void fail()
    {
        Q_ASSERT(false);
    }

    virtual void result()
    {
        Q_ASSERT(false);
    }
 }

class Command : public Responder, public ICommand
{
public:
    ....
}

class ConcreteCommand : public Command
{
public:
    void execute(Event* event)
    {
        .....
    }

public slots:
    void fail()
    {
        QMessageBox...
    }

    void result()
    {
        QMessageBox...
    }
}

Q_DECLARE_METATYPE(ConcreteCommand);




//где-то во фронт контроллере
#define REGISTER_COMMAND(clazz) { qRegisterMetaType<clazz>(); }
....
REGISTER_COMMAND(ConcreteCommand)



6. да, ты прав! вопрос можно было короче поставить smile но написал так на всякий пожарный: друг кому интересно для чего это + может по лучше понять проблему
PM WWW   Вверх
SABROG
Дата 23.10.2009, 11:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 81
Всего: 91



Цитата(chaos @  23.10.2009,  09:36 Найти цитируемый пост)
3. опечатки вроде нет smile Async сокращенно от Asynchronously


Цитата(chaos @  22.10.2009,  12:52 Найти цитируемый пост)
void AsynkToken::addResponder(IResponder *responder)


У тебя тут буква "k", вместо "c".


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
chaos
Дата 23.10.2009, 12:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Серийный программист
****


Профиль
Группа: Завсегдатай
Сообщений: 2979
Регистрация: 7.7.2004
Где: Екатеринбург

Репутация: 5
Всего: 44



SABROG, а да. сорри. невнимательность.


ЗЫ У кого-нить есть еще какие идейки?

ЗЫЫ почему низя удалить команду в слоте?
Код

void ConcreteCommand::result()
{
    .....
    delete this;
}

PM WWW   Вверх
SABROG
Дата 23.10.2009, 16:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 81
Всего: 91



Цитата(chaos @  23.10.2009,  12:31 Найти цитируемый пост)
У кого-нить есть еще какие идейки?


Если удаление должно происходить после result(), то как вариант можно посылать специальный event, который будет перехватывать основной класс или менеджер команд и удалять полученный указатель. В итоге возврата в удаленный объект не будет. Если не эвент, то сигнал с Qt::QueuedConnection, или QMetaObject::invokeMethod тоже с Qt::QueuedConnection или QTimer c 0 задержкой. Получится подобие deleteLater().

P.S.: delete this

Это сообщение отредактировал(а) SABROG - 23.10.2009, 17:53


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
chaos
Дата 23.10.2009, 20:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Серийный программист
****


Профиль
Группа: Завсегдатай
Сообщений: 2979
Регистрация: 7.7.2004
Где: Екатеринбург

Репутация: 5
Всего: 44



Цитата(SABROG @  23.10.2009,  13:50 Найти цитируемый пост)
Если удаление должно происходить после result(),

да, или после result или после fail
PM WWW   Вверх
SABROG
Дата 23.10.2009, 22:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 81
Всего: 91



Цитата(chaos @ 23.10.2009,  20:04)
Цитата(SABROG @  23.10.2009,  13:50 Найти цитируемый пост)
Если удаление должно происходить после result(),

да, или после result или после fail

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


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
chaos
Дата 26.10.2009, 09:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Серийный программист
****


Профиль
Группа: Завсегдатай
Сообщений: 2979
Регистрация: 7.7.2004
Где: Екатеринбург

Репутация: 5
Всего: 44



Цитата(SABROG @ 23.10.2009,  19:34)
Цитата(chaos @ 23.10.2009,  20:04)
Цитата(SABROG @  23.10.2009,  13:50 Найти цитируемый пост)
Если удаление должно происходить после result(),

да, или после result или после fail

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

не, как раз таки хочу пользоваться фишками Qt(например QMetaType, signals&slots, ....)

запостил топик именно сюда, тк думал что можно както-средствами QT можно решить проблему.

Только пока не придумал как, тк переопределив метод deleteLater не совсем понятно потом как его удалить

PM WWW   Вверх
SABROG
Дата 26.10.2009, 12:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 81
Всего: 91



А если сделать ICommand на базе QEvent?


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
chaos
Дата 26.10.2009, 12:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Серийный программист
****


Профиль
Группа: Завсегдатай
Сообщений: 2979
Регистрация: 7.7.2004
Где: Екатеринбург

Репутация: 5
Всего: 44



Цитата(SABROG @ 26.10.2009,  09:04)
А если сделать ICommand на базе QEvent?

а как тогда с асинхронностью дела будут обстоять?
те, идею я понял, QEvent'а по началу нового цикла обработки сообщений "убьют"(поправте если ошибаюсь).


PM WWW   Вверх
SABROG
Дата 26.10.2009, 13:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 81
Всего: 91



Цитата(chaos @  26.10.2009,  12:54 Найти цитируемый пост)
а как тогда с асинхронностью дела будут обстоять?


А чего им обстоять? Асинхронности в цикле событий как таковой не существует, если ты поставишь sleep() в каком нибудь обработчике эвента или слоте, то все остальные команды будут лежать в очереди, пока не произойдет выход из обработчика. То есть у тебя есть всего лишь очередь команд, которые выполняются последовательно. Вот многопоточность это уже асинхронность.

Если брать тот же как бы асинхронный QNetworkAccessManager, то на скорость скачивания файла и скорость соединения будет влиять время выполнения других методов программы. Если один из них подвесит на некоторое время программу, то эвенты от ОС могут прийти целым шквалом по возвращению в главный цикл событий.


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
chaos
Дата 26.10.2009, 13:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Серийный программист
****


Профиль
Группа: Завсегдатай
Сообщений: 2979
Регистрация: 7.7.2004
Где: Екатеринбург

Репутация: 5
Всего: 44



это я вроде все понимаю.
вот пример:
1. Команда у нас подкласс QEvent
2. когда приходит ивент мы у него дерним метод execute
3. внутри метода например вызовится метод сокеты connect + подпишемся на на сигналы. на этом метод execute закончится.
4. удалится ли "ивент" ?
PM WWW   Вверх
SABROG
Дата 26.10.2009, 13:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 81
Всего: 91



Цитата(chaos @  26.10.2009,  13:29 Найти цитируемый пост)
удалится ли "ивент" ? 


Цитата

The event must be allocated on the heap since the post event queue will take ownership of the event and delete it once it has been posted. It is not safe to modify or delete the event after it has been posted.



--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
chaos
Дата 26.10.2009, 19:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Серийный программист
****


Профиль
Группа: Завсегдатай
Сообщений: 2979
Регистрация: 7.7.2004
Где: Екатеринбург

Репутация: 5
Всего: 44



SABROG, вообщем не получается красивого решения найти.
у меня последний вопрос: на сколько опасно в рамках QT удалять самого себя в слоте, при том что я гарантирую что больше объект никому не понадобится?

PM WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Кроссплатформенное программирование, QT/Gtk+/wxWidgets"
JackYF
Любитель
  • В заголовке темы в квадратных скобках обозначьте используемую вами библиотеку, например: [QT],[GTK],[wx].
  • Если вопрос актуален только для некоторой версии библиотеки, либо, если вы пользуетесь не самой последней версией, укажите это. Например: [QT4], [GTK2].
  • Все начинающие изучать Qt - не забудьте зайти сюда.
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • В вопросе укажите полную версию версию библиотеки, а также все дополнительные используемые программные пакеты.
  • Не забывайте пользоваться кнопкой "Код".
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к тематике этого раздела. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, Любитель.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets | Следующая тема »


 




[ Время генерации скрипта: 0.0582 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.