LINUX.ORG.RU

Года бегут, а все-равно ваш C++ - ...

 ,


1

9

В соседнем треде промелькнула очень интересная мысль.

Отличие синьора-помидора на C++ от мидла в том, что последний уже знает что C++ говно, но еще не знает, почему.

Внимание, вопрос уровня синьора-помидора. Дан код. Объясните, почему другой синьор-помидор обосрался, написав его? Где может обосраться пользователь?

Задачу не будем усложнять, допустим, у нас single producer - single consumer предполагается.

#ifndef __BLOCKING_QUEUE_HPP__
#define __BLOCKING_QUEUE_HPP__

#include <cstdlib>
#include <mutex>
#include <condition_variable>

template<typename T>
class BlockingQueue
{
private:

    struct QueueNode
    {
        T val;
        QueueNode * next;
    };

    QueueNode *_first, *_last;
    std::mutex _cs;
    std::condition_variable _cv;
    bool _abort;
    int _count;

public:

    BlockingQueue()
    {
        _first = _last = nullptr;
        _abort = false;
        _count = 0;
    }

    ~BlockingQueue()
    {
        Flush();
    }
    
    BlockingQueue(const BlockingQueue& rhs) = delete;

    void operator=(const BlockingQueue& rhs) = delete;

    bool Put(const T& val)
    {
        std::unique_lock<std::mutex> lock(_cs);

        if(!_abort)
        {
            QueueNode * node = (QueueNode*)malloc(sizeof(QueueNode));
            if (node)
            {
                new (&node->val) T(val);
                node->next = nullptr;
                if (_last)
                    _last->next = node;
                else
                    _first = node;
                _last = node;
                ++_count;
                _cv.notify_one();
                return true;
            }
        }
        return false;
    }

    bool Get(T& val)
    {
        std::unique_lock<std::mutex> lock(_cs);

        for (;;)
        {
            if (_abort) return false;

            QueueNode * node = _first;
            if (node)
            {
                _first = node->next;
                if (!_first) _last = nullptr;
                --_count;
                val = node->val;
                node->val.~T();
                free(node);
                return true;
            }
            else
            {
                _cv.wait(lock);
            }
        }
    }

    int Count()
    {
        return _count;
    }

    void Flush()
    {
        QueueNode *node, *tmp;

        std::unique_lock<std::mutex> lock(_cs);

        for (node = _first; node; node = tmp)
        {
            tmp = node->next;
            node->val.~T();
            free(node);
        }

        _first = nullptr;
        _last = nullptr;
        _count = 0;
    }

    void Abort()
    {
        std::unique_lock<std::mutex> lock(_cs);
        _abort = true;
        _cv.notify_one();
    }

    void Start()
    {
        std::unique_lock<std::mutex> lock(_cs);
        _abort = false;
        _cv.notify_one();
    }
};

#endif // __BLOCKING_QUEUE_HPP__

Вопрос номер два - назовите хотя бы один язык программирования с подобными проблемами.

★★★
Ответ на: комментарий от intelfx

Потому что он написал аналог стандартно-библиотечной функциональности.

Это не стандартный библиотечный функционал. Правда, обычно подобное делают полностью на атомиках и несколько сложнее.

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

Это обычный C++ код, я тебя разочарую.

Задача очереди была хранить именно ресурсы. Которые текли и ебались куда-то. Там еще смешная вещь была - была std::move вместо просто оператора присваивания в Get - так это MSVC++ почему-то пропускал типа ок, даже у классов которые move semantics исповедуют - почему - не знаю. А unbounded это не критично, на практике работало, память не текла.

В итоге переписал на Си с классами, конечно, в виде lightweight COM.

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

Это обычный C++ код, я тебя разочарую.

Продолжаешь быть клоуном. За такой код везде дают по роже, особенно за наколеночную очередь под мьютексом.

anonymous
()

Отличие синьора-помидора на C++ от мидла в том, что последний уже знает что C++ говно, но еще не знает, почему

ого, мой уровень синьор с навыками лишь мидла )))

I-Love-Microsoft ★★★★★
()
Ответ на: комментарий от lovesan

Это обычный C++ код, я тебя разочарую.

Чувак, у меня есть код, реализующий, по всей видимости, то же самое, а именно - потокобезопасную очередь задач. И он ни разу не похож. Ты просто не читал Страуструпа и не видел C++-кода.

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

Это обычный C++ код, я тебя разочарую.

Не выдет. Я сегодня ещё хуже правил. Но это не значит что этот код написан на C++.

Там еще смешная вещь была - была std::move вместо просто оператора присваивания в Get

Ничего не понял! В смысле вместо val = node->val; былo val = std::move(node->val);?

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

Да. И это трактуется как rvalue, по видимому? Или как-то кастуется к нему, и вобщем, в обычном случае, как в оп-посте, то когда у класса move-семантика, MSVC говорит - ах ты ж, тут обращение к deleted функции(к оператору копирования), а в таком случае - все ок, проходит через конструктор копирования и оператор move-assignment. Как-то так. В итоге конечно, все-равно, говно получается, но еще хер поймешь почему.

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

Страуструп говно. Вместе с Александреску. Нахер нахер.

Я когда на плюсах пишу, то только lightweight COM, по минимуму стандартных коллекций(ну максимум map, vector), и всё. За остальное надо по рукам бить палкой.

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

Это обычный C++ код

За подобный C++ код из заборостроительного ВУЗ-а на первом курсе выгоняют, не то что с нормальной работы.

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

Очередь под мьютексами — вполне стандартная и библиотечная.

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от lovesan

Страуструп говно. Вместе с Александреску. Нахер нахер.

Ну всё с тобой тогда понятно.

Я когда на плюсах пишу

Никогда.

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

но когда у класса move-семантика

Всё ещё нихрена не понимаю. Я не знаю что такое «у класса move-семантика» и Стандарт не знает. Что имеется в виду?

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

оператор присваивания через копирование запрещен, и определены move-конструктор и присваивание

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

Так в чём именно вы влипли с вашим гогнокодом? Ты уже столько слов написал, но до сих пор не понятно что вы сделали не так. Где-то выже мелькал SuperCoolRAIIResourceWrapper и если это и есть ваша проблема, то, очевидно, вы обосрались с реализацией T, а не очереди.

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

оператор присваивания через копирование запрещен, и определены move-конструктор и присваивание

С тобой просто невозможно общаться! Ну напиши хоть на C++ что и как определено, если по-человечески говорить разучился!

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

есть фрейм ffmpeg, надо его складывать в q, и потом доставать

фрейм выделен через av_frame_alloc, плюс у него еще refcount буфер внутри

оказалось проще написать специфическую для него очередь, чем дрочить C++

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

фрейм выделен через av_frame_alloc

Понятно, вопль неосиляторов. Не разобравшись полезли лепить SuperCoolRAIIWrapper и обосрались на ровном месте. Типичная история крестомакакенов.

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

лол

если у тебя нормальная архитектура, модульная там, с сорсами и синками - ты че, по стеку гонять фреймы будешь? Тем более, разработчики говорят - единственная структура, на которую вы можете закладываться, класть на стек и так далее - это AVPacket. Про фреймы уже ни слова.

lovesan ★★★
() автор топика
Последнее исправление: lovesan (всего исправлений: 1)
Ответ на: комментарий от lovesan

если у тебя нормальная архитектура, модульная там, с сорсами и синками - ты че, по стеку гонять фреймы будешь?

Не по стеку. Очередь для обработки вполне правильное решение. А вот wrapper поверх этого всего дрянной оказался. Что мешало изначально завести:

  • FIFO queue из shared_ptr — очередь фреймов в порядке их поступления
  • одна или несколько очередей процессинга из weak_ptr-ов

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

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

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

А ты шаришь :-) Хм :-) Молодец :-)

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

move-constructor и оператор это вообще-то стандартные вещи, ну типа там && и все такое

Фишка в том, что если объявляешь конструктор копирования, оператор присваивания или деструктор (а понятие «объявляешь» подразумевает *любой* тип объявления в т.ч. defalut/delete), то move-конструктор и move-присваивание не создаются. А раз они не создаются, то не участвуют в «конкурсе на лучшую невесту», сиречь overload resolution.

std::move не подразумевает, что компилятор выкидывает ошибки в случае невозможности использовать move-версии. Но в случае явного delete, соответствующий метод будет участвовать в overload resolution, но поскольку невеста явно объявлена дохлой, то компилятор обидится.

Короч. говоря в случае r-value reference компилятор удовлетворится и версиями с копированием. В случае попытки сделать move(const lvalue) чуда тоже не произойдет.

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

фрейм выделен через av_frame_alloc, плюс у него еще refcount буфер внутри

Ну ты совсем тупой, покажи с++ класс который использовался в очереди, с конструкторами и оператором=(...).

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

Ну вот и завели специфические для AVFrame очереди, только без C++ изврата, без shared_ptr и прочего. Работает - идеально. Код - проще некуда.

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

оказалось проще написать специфическую для него очередь, чем дрочить C++

Тебя на протяжении всего треда спрашивают уже не один раз что вы наделали с с++ классами, а ты в ответ несёшь какую-то ахинею про «класс реализующий rvalue» и «классов которые move semantics исповедуют». А теперь вот зачем то поделился сношениями с ffmpeg, хотя это никого тут не интересует.

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

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

Потому что синьоры и мидлы не берут готовые решения, а изобретают свои велосипеды.

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

1 класс в оп-посте.

Второй класс безуспешно пытались адаптировать к первоему, в том числе через смартпойнтеры, а в итоге забили и написали простую q, с сишной семантикой, для специфического типа. Что тебе непонятно?

Нам знаешь ли важно время, value продукта, и красота и простота кода, а не ачивки в задротстве на C++

lovesan ★★★
() автор топика
Последнее исправление: lovesan (всего исправлений: 1)
Ответ на: комментарий от lovesan

1 класс в оп-посте.

Гле класс T?

Нам знаешь ли важно время, value продукта, и красота и простота кода, а не ачивки в задротстве на C++

Если вам важно время, то вам нужно тебя хернуть ногой под зад на мороз.

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

Три момента:

1) С COM-компонентами(DirectX/MF/etc) такого геморроя не было вообще от слова совсем.

2) С высокоуровневыми языками и близко такого нет.

3) Если спуститься до уровня банальной сишечки, то оказывается, все становится настолько проще, понятнее, контролируемее и вменяемее, что я даже не знаю как описать.

А про неосиляторство дальше рассказывайте сказки в кружке невменяемых дрочеров на плюсы.

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

компилятор может создать по регистровому «экземпляру» переменной на тред в процессе оптимизации и изменения не будут расшарены.

Держать в регистрах он может до вызова _cv.notify_one() и free(), дальше компилятор выдаёт код, который делает программу вести себя as if это виртуальная машина из стандарта, т.е. становятся видимыми все side effects, которые должны были произойти до вызова функции/возврата из функции.

anonymous
()

Года бегут, а наш lovesan... продолжает использовать язык программирования с кривыми программистами. А мог бы использовать lisp, ведь он сам за себя код писать умеет, и работает очень быстро.

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

Не забудь сделать free на node, если конструктор выкинет исключение.

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

виртуальная машина из стандарта

Конечно же «абстрактная».

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

Да, то, что я написал в предыдущем сообщении, оно конечно не гарантирует ничего. В регистрах компилятор не оставит, но на архитектурах со слабой когерентностью кешей могут быть проблемы.

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

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

Поддержу тебя в том что код должен быть простым.

deep-purple ★★★★★
()
Последнее исправление: deep-purple (всего исправлений: 1)
Ответ на: комментарий от deep-purple

С плюсами знаком лет 10. Но все-равно, признаю, что да, есть некоторый порог, после которого дальше - осиливать это дерьмо - себе дороже. Это только совсем невменяемые могут себе позволить.

lovesan ★★★
() автор топика

проблема не в коде, а в твоём работодателе

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

anonymous
()

Не ври. Это не сеньор писал, а студент какой-то.

invy ★★★★★
()

опять с++ насрал в шаровары великому программисту. Астанавись, с++! хватит срать в шаровары ловесану.

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

Но это не значит что этот код написан на C++.

А этот код написан не на перле:

 cat "test... test... test..." | perl -e '$??s:;s:s;;$?::s;;=[=>%-{<-|}<&|`{;;y; -/:-@[-`{-};`-{/" -;;s;;$_;see'
MyTrooName ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.