Я бы сказал, что программисту на любом языке полезно изучать другие технологии, в том числе те, которые применяются в других областях индустрии. Это выводит уровень решения задач на принципиально новый.
Минусуют за то, что не различаете компилятор и IDE.
И это, в CodeBlocks используется GCC. А значит сам редактор тут не при чем.
PS. я минусов не ставил.
1) Это да. Передача через event`ы эту проблему решает.
2) Я не считаю это проблемой, все равно интерфейс, определенный в MyThread будет привязан к конкретной задаче. Класс на практике называться будет соответственно этой задаче (а не MyThread). С другой стороны этот способ точно так же довольно просто поддаётся шаблонизации. Поэтому, если уже очень хочется, можно придумать нечто обобщённое на этой базе.
К слову сказать с более ранних версиях Qt event based межпоточное взаимодействие было основным способом. Т.к. во-первых поток не имел своей встроенной очереди сообщений, как в Qt4-Qt5, а во-вторых система сигналов не поддерживала межпоточные соединения. Приходилось делать свою очередь сообщений внутри run и проектировать систему событий для потока. Зато можно было передавать в основной поток события с помощью функции postEvent (собственно сейчас так тоже можно).
В журнале DrDobbs помню статью (к сожалению ссылку найти не могу), в которой показывались приемы работы с многопоточностью в Qt.
Одна из концепций такова (демонстрационный пример):
class MyThreadImpl
: public QObject
{
Q_OBJECT
public:
MyThreadImpl();
public slots:
void doStuff()
{
// impl...
emit onSomeStuff();
// impl
}
signals:
void onSomeStuff();
};
class MyThread
: public QThread
{
Q_OBJECT
public:
void doStuff()
{
emit doStuffImpl();
}
signals:
// external
void onSomeStuff();
// internal
void onStuffImpl();
private:
void run()
{
MyThreadImpl threadImpl;
// signal to thread
connect(this, SIGNAL(onStuffImpl()), &threadImpl, SLOT(doStuff()));
// signal from thread
connect(&threadImpl, SIGNAL(onSomeStuff()), this, SIGNAL(onSomeStuff()));
exec();
}
};
Со своей стороны нахожу данный подход одним из самых удачных для Qt и всем его рекомендую. Функции типа moveToThread считаю костылями, призванными исправлять существующие архитектурные косяки в проекте. Использовать их для новых решений ИМХО не стоит.
Аналогичный, более классический пример с использованием QEvent, который несколько более многословен, однако дает лучшую производительность.
while и for помимо своей цикличности вносят еще и область видимости. Это особенно важно для С++. Поэтому если и использовать goto, то с фигурными скобками:
int main ()
{
loop:
{
printf("1\n");
}
goto loop;
}
Получается даже немного длинее. Нет, все-таки в этом случае право большинство: for и while — лучше.
Хрень говорил. Геморрой — суть болезнь от плохого кровообращения. То есть сидишь ты весь день на заднице, застой крови образуется — как следствие — геморрой. У велосипедистов такого быть не может — ибо мышцы ягодичные всегда в тонусе. Да и массаж от седла неплохой.
Как раз таки не через Си-код. А в обход его. Задача во-первых не допустить попадания в Си-код исключений и нарушения контракта. Во-вторых оставить для пользователя библиотеки возможность их генерировать (в моем случае неизбежно, потому что код уже написан).
Смысл «протаскивания» в том, что обработка исключения должна быть в том месте, где это нужно. Если переносить всю обработку в код враппера — это будет прямое нарушение инкапсуляции. Враппер просто не может знать об особенностях клиентского кода.
Ну так а я не говорю про С. Я говорю для С++, почему бы не прочитать вопрос habrahabr.ru/blogs/cpp/100623/#comment_3113697, прежде чем дискуссию начинать? :) Я объяснял, что код который вызывается из Си не защищен от С++-исключений. В случае callback`ов в Си библиотеках, это тоже самое, что если бы код на Си вызывал С++ код.
Причем я как раз отметил чем это чревато и почему нельзя такого допускать.
В чем идея? Есть либина XML, к ней есть С++ враппер. С++ враппер С++ библиотека? Да. Почему бы не использовать вместе с ней исключения. Однако в недрах враппера юзаются коллбэки, который выполняются в Си коде. Потому что враппер — над С-XML-либиной. Так как разрешить проблему? СС одной стороны как бы юзер враппера не виноват, он же юзает С++, с другой стороны ему вдруг нельзя использовать исключения. Это решение этой проблемы.
Да, основная идея в том, чтобы код, который использует MyLib не вынуждать отказываться от исключений. Чтобы этот код претерпел как можно меньше изменений. Для этого надо их где-то запомнить, а прежде чем запомнить, надо их отфильтровать.
Шаблоны — для удобстве фильтрации. Если в mylib не один callback, а 10, и в каждом callback`е написано нечто вроде: try
{
this_->callback();
}
catch(exception1)
{
}
catch(exceptionN)
{
}
Особенно если нужно добавить новое исключение, все это превращается в жуткую кашу. А у меня достаточно в одном месте дописать нужный тип в список исключений.
> Я не зря привел в пример expat. Проблема исключений встала именно при использовании этой
> библиотеки. Задача состояла в следующем:
> * Есть некий код, который раньше использовал библиотеку xml, написанную на С++ и этот код
> активно применял исключения;
> * Есть необходимость заменить библиотеку xml на другую без переписывания остального кода.
В данном контексте с ним все в порядке. Я сам передал указатель this, скастив его к void*, сам его же и забрал и скастил обратно. pureCLibSetUserData(this);
Так он и не знает. В этом и проблема. И при исключении функция не возращает никакого результата. Она прерывается альтернативно с раскруткой стека. Как это реализовано конкретно — зависит от компилятора.
> А зачем бросила?
Предлагается решение, при котором такого вопроса бы не возникало. Исключение не должно покидать пределы С++.
> Предлагается костыль для кривых библиотек?
В C++ исключения — это нормальное явление, new кидает исключение, dynamic_cast кидает искючения, STL кидает исключения. Кривизна библиотеки будет только тогда, когда она позволит исключению попасть в чужую среду.
— Совковая лопата говно, я весь участок штыковой перекопал, очень удобно! 5 лет до этого копал совковой, ну и извращенцы же ее придумали!
Заканчивайте с этим, короче. Эмоции в инженерии — лишнее дело.
И это, в CodeBlocks используется GCC. А значит сам редактор тут не при чем.
PS. я минусов не ставил.
2) Я не считаю это проблемой, все равно интерфейс, определенный в MyThread будет привязан к конкретной задаче. Класс на практике называться будет соответственно этой задаче (а не MyThread). С другой стороны этот способ точно так же довольно просто поддаётся шаблонизации. Поэтому, если уже очень хочется, можно придумать нечто обобщённое на этой базе.
К слову сказать с более ранних версиях Qt event based межпоточное взаимодействие было основным способом. Т.к. во-первых поток не имел своей встроенной очереди сообщений, как в Qt4-Qt5, а во-вторых система сигналов не поддерживала межпоточные соединения. Приходилось делать свою очередь сообщений внутри run и проектировать систему событий для потока. Зато можно было передавать в основной поток события с помощью функции postEvent (собственно сейчас так тоже можно).
Одна из концепций такова (демонстрационный пример):
Со своей стороны нахожу данный подход одним из самых удачных для Qt и всем его рекомендую. Функции типа moveToThread считаю костылями, призванными исправлять существующие архитектурные косяки в проекте. Использовать их для новых решений ИМХО не стоит.
Аналогичный, более классический пример с использованием QEvent, который несколько более многословен, однако дает лучшую производительность.
Получается даже немного длинее. Нет, все-таки в этом случае право большинство: for и while — лучше.
Смысл «протаскивания» в том, что обработка исключения должна быть в том месте, где это нужно. Если переносить всю обработку в код враппера — это будет прямое нарушение инкапсуляции. Враппер просто не может знать об особенностях клиентского кода.
Причем я как раз отметил чем это чревато и почему нельзя такого допускать.
В чем идея? Есть либина XML, к ней есть С++ враппер. С++ враппер С++ библиотека? Да. Почему бы не использовать вместе с ней исключения. Однако в недрах враппера юзаются коллбэки, который выполняются в Си коде. Потому что враппер — над С-XML-либиной. Так как разрешить проблему? СС одной стороны как бы юзер враппера не виноват, он же юзает С++, с другой стороны ему вдруг нельзя использовать исключения. Это решение этой проблемы.
Шаблоны — для удобстве фильтрации. Если в mylib не один callback, а 10, и в каждом callback`е написано нечто вроде:
try
{
this_->callback();
}
catch(exception1)
{
}
catch(exceptionN)
{
}
Особенно если нужно добавить новое исключение, все это превращается в жуткую кашу. А у меня достаточно в одном месте дописать нужный тип в список исключений.
> Я не зря привел в пример expat. Проблема исключений встала именно при использовании этой
> библиотеки. Задача состояла в следующем:
> * Есть некий код, который раньше использовал библиотеку xml, написанную на С++ и этот код
> активно применял исключения;
> * Есть необходимость заменить библиотеку xml на другую без переписывания остального кода.
pureCLibSetUserData(this);
//...
MyLib * this_ = reinterpret_cast<MyLib*>(userData);
Предлагается решение, при котором такого вопроса бы не возникало. Исключение не должно покидать пределы С++.
> Предлагается костыль для кривых библиотек?
В C++ исключения — это нормальное явление, new кидает исключение, dynamic_cast кидает искючения, STL кидает исключения. Кривизна библиотеки будет только тогда, когда она позволит исключению попасть в чужую среду.