Pull to refresh
24
0
Send message
Знаете как это все выглядит?

— Совковая лопата говно, я весь участок штыковой перекопал, очень удобно! 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 кидает исключения. Кривизна библиотеки будет только тогда, когда она позволит исключению попасть в чужую среду.
> А зачем бросила?
Ну, давайте немного упростим ситуацию. Представьте, что вы пишете на языке Си и подключаете к проекту библиотеку написанную на С++. Библиотека эта, предположим, экспортирует функции, помеченные как extern «C», то есть такие функции свободно можно из Си вызывать. Так вот. Теперь представьте, что одна из таких функций бросила исключение. Куда оно попадет? И какие в Си есть возможности для его перехвата?
Пример на Си:
void foo(int (*callback)(char *))
{
char * buffer;
int ret;

buffer = malloc(100000);
ret = callback(buffer);
free(buffer);
}

Если сallback — это функция из С++, то она может бросить исключение. При этом будет утечка памяти, так как buffer не будет освобожден.
Конечно, без крайней необходимости прибегать к такому я бы тоже не стал. Если проектировать систему с нуля, то такие вещи нужно прогнозировать. Однако у меня был уже готовый проект, который нужно было портировать на платформу, где QtXML (именно она и есть та С++ xml-библиотека) не существовало в природе, а был только expat.

Information

Rating
Does not participate
Location
Россия
Registered
Activity