Обновить
24

Пользователь

5
Подписчики
Отправить сообщение
Можно было бы убрать повторяющиеся вычисления и сделать код немного короче.
Не доказали.
Я бы сказал, что программисту на любом языке полезно изучать другие технологии, в том числе те, которые применяются в других областях индустрии. Это выводит уровень решения задач на принципиально новый.
Знаете как это все выглядит?

— Совковая лопата говно, я весь участок штыковой перекопал, очень удобно! 5 лет до этого копал совковой, ну и извращенцы же ее придумали!

Заканчивайте с этим, короче. Эмоции в инженерии — лишнее дело.
Минусуют за то, что не различаете компилятор и 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 — лучше.
Хрень говорил. Геморрой — суть болезнь от плохого кровообращения. То есть сидишь ты весь день на заднице, застой крови образуется — как следствие — геморрой. У велосипедистов такого быть не может — ибо мышцы ягодичные всегда в тонусе. Да и массаж от седла неплохой.
Даже если я это сделаю — она (си-библиотека) же не написана с учетом exception-safety.
Как раз таки не через Си-код. А в обход его. Задача во-первых не допустить попадания в Си-код исключений и нарушения контракта. Во-вторых оставить для пользователя библиотеки возможность их генерировать (в моем случае неизбежно, потому что код уже написан).

Смысл «протаскивания» в том, что обработка исключения должна быть в том месте, где это нужно. Если переносить всю обработку в код враппера — это будет прямое нарушение инкапсуляции. Враппер просто не может знать об особенностях клиентского кода.
Так он это и делает вообще-то. Вы статью читали?
И где противоречие с тем, что я написал?
Ну так а я не говорю про С. Я говорю для С++, почему бы не прочитать вопрос 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);

//...

MyLib * this_ = reinterpret_cast<MyLib*>(userData);

Значит библиотеки boost или stl по-вашему ошибочны по своей природе, раз позволяют исключениям передаваться за свои границы?
Так он и не знает. В этом и проблема. И при исключении функция не возращает никакого результата. Она прерывается альтернативно с раскруткой стека. Как это реализовано конкретно — зависит от компилятора.
> А зачем бросила?
Предлагается решение, при котором такого вопроса бы не возникало. Исключение не должно покидать пределы С++.

> Предлагается костыль для кривых библиотек?
В C++ исключения — это нормальное явление, new кидает исключение, dynamic_cast кидает искючения, STL кидает исключения. Кривизна библиотеки будет только тогда, когда она позволит исключению попасть в чужую среду.

Информация

В рейтинге
Не участвует
Откуда
Россия
Зарегистрирован
Активность