• C++ template аллокатора с потокобезопасным циклическим буфером
    0
    Нет, дело не в memory order, а в простой логике.
    Например (это только один из примеров, думаю можно найти больше)
    1) Мы дошли до последней строчки этого кода, не успев ее выполнить и «зависли»
    2) При этом available у нас уже сброшено в Leaf_size
    3) Какойто поток приходит, видит что в available чтото есть, берет память и отдает.
    4) Потом опять берет много-много (всю память) и всю ее отдает обратно. В результате available == 0, а в deallocated 2 * Leaf_Size_Bytes, мы не проходим проверку if (deallocated == (Leaf_Size_Bytes — available)) и выходим из этого куска кода
    5) Просыпается наш зависший поток, и производит уменьшение. В результате deallocated == Leaf_Size_Bytes
    6) Никто не может взять новый кусок памяти, так как available == 0
    7) Никто не может войти в этот кусок кода, так как для того чтобы сюда войти, нужно выполнить освобождение, а освобождать нечего, так как никто ничего не может взять
  • C++ template аллокатора с потокобезопасным циклическим буфером
    0
    В этом куске кода

    if (deallocated  == (Leaf_Size_Bytes - available))
          {  // everything that was allocated is now returned, we will try, carefully, reset the Leaf
            if (leaf_array[head->leaf_id].available.compare_exchange_strong(available,  Leaf_Size_Bytes))
            {
              leaf_array[head->leaf_id].deallocated  -=  deallocated;
            }
          }


    Что будет, если после compare_exchange_strong поток «зависнет» (планировщик потоков ос например отдаст ядро комуто другому) и в этот момент другие потоки продолжат пользоваться этим листом, забирая и возвращая куски памяти?
  • Как получить работу мечты благодаря смертельному диагнозу
    +2
    > В общем, то, на что давалось 4 месяца, я запустил за 4 недели
    > а в получении контракта не было сомнений – такой ядерной работоспособности в компании никто ранее не встречал

    Я надеюсь, дальше вы работали с таким же усердием?
  • Как перезапустить закон Мура программными методами. Ускорение софта в тысячи раз
    +6
    Хм, почему сейчас ПО по-вашему «развивается», а вскоре вдруг перестанет? Нет, ну может быть лет через 50 такое и наступит, но мне к тому моменту будет уже глубоко на это пофиг
  • Как перезапустить закон Мура программными методами. Ускорение софта в тысячи раз
    +8
    Если сейчас (да и раньше) программисты писали на медленных яваскрипт и python, то почему через несколько лет, когда производительность еще вырастет, и только потом остановится, все сразу убегут на C++?
  • can_throw или не can_throw?
    +1
    Уу, тоесть у вас то, добавлять гуард к функции или не добавлять, еще зависит от того, из какого контекста функция вызывается? Тогда уж точно макросы проще
  • can_throw или не can_throw?
    0
    Не понял насчет статической типизации. Ну вот например есть такая функция
    optional<S> parse(json) {
        S result;
        if (!json.contains("id")) 
            return nullopt;
        result.id = json.get<int>("id");
        if (!json.contains("value"))
            return nullopt;
        result.value = std::stol(json.get<string>("value"));
        if (!json.contains("type"))
            return nullopt;
        result.type = json.get<string>("type");
        return result;
    }


    Нужно ли в него вставлять этот дополнительный параметр?
  • can_throw или не can_throw?
    0
    Мне кажется, выцепить глазом отсутствие макросов намного проще, особенно если взаимодействие с asio вынесено в файлы отдельных типов (как в mvc — модель отдельно, контроллер отдельно… asio отдельно). А как глазами выцепить, что в функции нужен лишний параметр, я даже не представляю
  • can_throw или не can_throw?
    +1
    К сожалению, никто не мешает написать метод, не принимающий can_throw, но бросающий исключение.
    Мне кажется, было бы проще обязать всех ставить к-нить макросы вокруг коллбэков, вроде
    BEGIN_EXCEPTION_HANDLER {
    // work
    } END_EXCEPTION_HANDLER
  • Вероятно, хватит рекомендовать «Чистый код»
    0
    Когда вам надоест писать метакод, и вы спуститесь на уровень пониже, то увидите, сколько вариантов может генерировать одна настоящая функция.

    Сколькими способами можно например написать такую функцию?
    fn: Int -> Int
    Одним? Двумя?… Миллиардом?
  • Cложный код или история одного интервью
    +1
    И в чем же моя лексика размыта и эмоционально заряжена?

    Ну вот например Роберт Мартин в книге «чистая архитектура» говорит
    > А что кричит архитектура вашего приложения? Увидев высокоуровневую структуру каталогов и пакетов с исходным кодом, услышите ли вы, как она кричит: «Это медицинская система», или «Это система учета», или «Это система управления складским хозяйством»? Или вы услышите: «Rails», или «Spring/Hibernate», или «ASP»?

    Плюс неоднократно слышал похожие мысли по разным углам.
  • Cложный код или история одного интервью
    0
    Меняется. Посмотрите кодстайлы различных компаний. Да, в основном они боле-менее похожи, но в чем-то различия всеже есть (иначе не было бы всеэ этих кодстайлов).
    Да, не нужно менять кодстайл каждый вторник, но что-то приятное или полезное со временем утянуть может быть стоило бы?
  • Cложный код или история одного интервью
    0
    > Я сам когда-то пришел в Java из С++ и называл переменные и методы через snake_case

    А я наоборот, пришел из явы и называл (и до сих пор называю) в C++ переменные через camelCase (или как он там называется). Вот и пример удачной коллаборации.

    > Это не колаборация дала, а просто на волне хайпа разработчики языков добавляют то, что пошло в других языках

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

    Заодно можно узнать особенности чужой платформы. Неужели Spring/Boot не допускает другой структуры проекта?
  • Cложный код или история одного интервью
    0
    Я конечно совсем не ява программист, и не знаю, как у вас принято, но мне кажется странным назвать папки и файлы именами паттернов. controller, view, domain… Искать нужный класс, да и вообще разобраться в структуре программы в таком случае, имхо, довольно сложно
  • Навык поиска работы
    0
    И как, потом переписали нормально?
  • С++ Concept-Based Polymorphism в продуктовом коде: PassManager в LLVM
    0
    А зачем runOnModule, runOnFunction...? Нельзя просто run?
  • Почему функциональное программирование такое сложное
    +4
    Потомучто эти адепты боятся хоть в запятой ошибиться при объяснении простых вещей. Ведь тогда другие такиеже адепты их заклюют и выбросят из своей культуры.
  • С++ Concept-Based Polymorphism в продуктовом коде: PassManager в LLVM
    +1
    Так и не понял, чем это лучше отдельных базовых классов с методом run
  • Оптимальный путь новичка в мире C++/Qt
    0
    Да, я и говорил про «пример построения текстового редактора» (только мне казалось, что оно идет в начале, а не в конце). Про сами паттерны читать там довольно скучно
  • Оптимальный путь новичка в мире C++/Qt
    0
    > Сколько я книг не читал (довольно мало на самом деле), никогда не находил в них ответа на вопрос, как написать приложение уровня Photoshop.

    В первой половине «банды четырех» описывается пример создания текстового редактора похожего на word
  • Вышел Windows Terminal 1.0
    0
    А историю введенных команд добавили?
  • C++/Qt: пора валить?.
    0
    В принципе, через ThreadManager можно и QObject-ы с signal-slot-ами работать. Как-то задумывался над этим, но не пробовал реализовать
  • C++/Qt: пора валить?.
    0
    Я както задумался, и пришел к выводу, что нету другого простого способа управлять ресурсами в Qt модели не через parent-child. Ну например, хотите вы сделать обертку над тредом, что-нить типа такого
    class ThreadWrapper {
        virtual void run() = 0; // Этот метод будет запущен в потоке
        void start() { // Запуск потока }
        ~ThreadWrapper() {
               // Остановка потока
         }
    }
    


    Вот только проблема в том, что когда выполнение программы дойдет до деструктора ThreadWrapper, производный класс уже будет уничтожен, и стопать в этот момент тред уже бесмысленно (скорее всего он там уже что-то напортил, так как работал с методом уничтоженного класса).

    Как эту проблему решить не через parent-child?
  • Почему WSL 2 в 13 раз быстрее, чем WSL: впечатления от Insider Preview
    0
    Возможно wine был бы и не нужен, если бы винда была бесплатная
  • Почему WSL 2 в 13 раз быстрее, чем WSL: впечатления от Insider Preview
    +2
    Когда-то читал статью о разработке первой WSL. Там эмулировались вызовы linux-а через window-ое окружение. Сейчас как я понимаю, всю WSL переписали с нуля, встроив чистый linux. Так был ли в итоге смысл в WSL1? Или она появилась лишь вследствие всем известного «фатального недостатка»?
  • Playrix выплатит сотрудникам по 50 000 ₽, чтобы помочь на время пандемии
    +1
    В свое время, когда я устраивался туда работать, мне сбили зарплату на 10% от запрошенной суммы. Типа — поработаешь полгодика, поднимем до запрошенной. Не подняли…
    Офигеть какая забота
  • Какие алгоритмы разработчики Яндекса реализовывают каждый день
    0
    Тем не менее, задачи довольно простые, за исключением разве что второй. Несравнимо с тем, на чем обычно гоняют на собеседованиях
  • Какие алгоритмы разработчики Яндекса реализовывают каждый день
    0
    Тем не менее, 2 замечания остаются в силе. Во-первых это
    > size_t position = mersenne.GenRand64() % passedItems;

    Во-вторых, можно обойтись без последнего shuffle-а, если последний if заменить на
            if (sample.size() < ItemsToTake) {
                sample.push_back(input->GetRow());
                std::swap(sample.back(), sample[position];
            } else {
                sample[position] = input->GetRow();
            }
    
    
  • Какие алгоритмы разработчики Яндекса реализовывают каждый день
    0
    Немного подумал, всетаки алгоритм больше похож на правду, чем я изначально предполагал.
  • Какие алгоритмы разработчики Яндекса реализовывают каждый день
    0
    Если после прохождения нескольких 5-часовых интервью коллеги пишут такой код…

    > Будем обрабатывать элементы по одному, слева направо; рассматривая очередной элемент с номером i, сгенерируем случайное число от 0 до i включительно и обменяем значениями текущий элемент и элемент на выбранной позиции.

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

    > size_t position = mersenne.GenRand64() % passedItems;
    Это не эквивалентно тому, чтобы выбрать (равномерно) случайный элемент из диапазона 0..i.
    Рассмотрите например случай если GenRand64 всегда ограничен дипазоном 0..4 включительно (для простоты рассуждения), а passedItems == 4. Тогда результат position == 0 будет встречаться чуть-чуть почаще, чем результат position == 1 например

    Дальше, в основном алгоритме перемешивания элементы нужно свопать друг с другом. У вас этого нет. Вы уверены, что подход правильный? Где доказательство?

    > if (sample.size() < ItemsToTake) {
    sample.push_back(input->GetRow());
    } else {
    sample[position] = input->GetRow();
    }

    Вы уверены, что это выдаст (если исправить все предыдущие замечания) равномерно распределенный набор данных? Хотелось бы послушать доказательство

    > Shuffle(sample.begin(), sample.end(), mersenne);
    Так ли нужно в конце перешафливать массив еще раз? Неужели нельзя построить сразу зашафленный?
  • Мой опыт стажировки в Microsoft Redmond и получения офера
    0
    Вопрос, который наверно интересует всех больше всего: пропорционально ли усилие, затраченное на подготовку и прохождение собеседований, усилиям в обычном рабочем процессе? И какой коэффициент пропорциональности?
  • Линеаризуем асинхронный код с помощью корутин
    0
    auto print = [](int a, int b) {
        std::cout << a << b;
    };
    auto receivedNewB = [print](int a) {
        abActor.getB(std::bind(print, a, _1));
    };
    auto receivenNewA = [receivedNewB]() {
        abActor.getA(receivedNewB);
    };
    auto saveAB = [receivenNewA](int a, int b) {
        abActor.saveAB(a, b, receiveNewA);
    };
    ...
    


    Чуть подредактировал, вроде лучше стало
  • Линеаризуем асинхронный код с помощью корутин
    0
    Это мы уже когдато обсуждали. Писать future.then для того, чтобы написать future.then для этой статьи мне кажется слишком. Одна из целей почти любой статьи «напугать» читателя неправильным подходом, и показать красивый «правильный» подход. Добавление future еще больше напугать читателя не смогло бы. И помочь решить проблему тоже. И поэтому смысла вводить я не вижу.

    В чем смысл вводить future, чтобы тутже от него отказаться?
    Если хочется иметь красивый линейный код в варианте с коллбэками, то его несложно устроить и без всяких future.
  • Линеаризуем асинхронный код с помощью корутин
    0
    Этот пример показывает, что код на корутины можно переписать частично. Не обязательно перерефакторивать весь проект, чтобы заюзать возможность использовать корутины. Если нам нужна в какойто функции корутина, мы пишем обертки и используем.

    Другой вопрос в том, как много этих оберток нужно написать. Сами классы для работы корутин — CoroTask, Awaiter, Resumable пишутся один раз и их можно использовать везде. Но для того, чтобы иметь возможность вызывать «акторный» метод из существующего «актора», для каждого такого метода придется писать доп. обертку. Насколько это применимо? Насколько это удобно в конкретном коде? Это решать уже читателям статьи
  • Линеаризуем асинхронный код с помощью корутин
    0
    Спасибо. Вот это — примерно то, что я ожидал от Вас в первом ну или хотябы во втором сообщении. Давайте теперь более предметно разберем

    1) Про GetACallback. В принципе понятно. Я тоже, когда работал над этим примером, думал, стоит ли тащить эту обертку над коллбэком или сделать предложенным Вами методом. Склонился к обертке. Склонился потому, что она обеспечивает более «надежный», хоть и более многословный код. Я правда думал, стоит привносить эту лишнюю надежность в обучающую статью или не стоит, и решил, что хуже не будет. Заодно отсечет лишние вопросы, которые лично я бы автору статьи в таком случае задал.

    Ну тоесть ответ такой, что эта обертка просто переносит контроль надежности кода из одного места в другое. Обидно, что из-за этого куска кода развернулась такая полемика. Мне казалось, что я наоборот «изобрел» что-то такое, что можно было бы взять на вооружение.

    2) Вот как раз в моем понимании акторы — это всегда асинхронность. Сейчас мы конечно опять начнем полемику о том, что представляют из себя акторы, но я всеже рискну.
    Можно ли было сделать этот метод синхронным? Да, но тогда его можно было бы вызвать из разных потоков. Но в этом случае, нам пришлось бы оборачивать среду этого метода в примитивы синхронизации.
    Лично я считаю, что программист должен выбирать между акторным подходом, но без мьютексов, или мьютексы, но не-акторный подход. Иначе получается так, что мы огребаем все недостатки как мьютексов, так и акторов, не приобретая никаких достоинств.

    Конечно, в реальности все может быть намного сложнее, и в какойто момент для предотврощения распростронения callback hell может оказаться необходимо переделать метод с асинхронного на синхронный, привнеся в код ненавистные мьютексы. Но это обсуждение точно не для обучающей статьи.

    3) Про future. Да, такой вариант есть. Но есть как минимум 2 момента — во-первых, коллбэки никуда не пропадают, во-вторых, нужен метод future.then. Но у стандартных future нету метода then. Вроде бы его обещали преподнести как раз в C++20 (но сейчас я его там уже чтото не вижу), но зачем, если у нас и так там уже появятся корутины?

    4) Про осмысленный пример. Ок, принято. Я конечно не считаю, что пример должен быть настолько осмысленным, как Вы привели, но признаю, что нормальной осмысленности мне всеже не хватило.
  • Линеаризуем асинхронный код с помощью корутин
    0
    Судя по «независимым комментариям», я статью не переусложнил. А недообъяснил. Не пояснил, почему контекст лямбды должен выполняться на треде, где был создан. Если бы Вы мне это сказали, я бы это понял первым же сообщением.

    Сейчас вы скажете, что Вы это и называете «переусложнил». Отлично. Сколько копий сломано из-за обсуждения значения слова, вместо того, чтобы просто взять и показать на проблему
  • Линеаризуем асинхронный код с помощью корутин
    +1
    Ну мнеже как автору тоже хочется понять, что не так? Ваше право — объяснять мне это или нет, мое — попытаться понять затруднения. И почемуто разговор с Вами досихпор не добавил мне понимания.

    Обидно, что столько времени потрачено впустую. Я просто думал, что у Вас действительно есть какоето супер решение, которое все прояснит. Но я ваше решение не понимаю. Как и Вы мое. Честно. Не троллю, не придираюсь, не понимаю. И, равняя по себе, представляю себе, что и другой читататель не поймет
  • Линеаризуем асинхронный код с помощью корутин
    0
    В его контексте исполняется std::cout и вызов актора abActor.
    Представьте, что вместо std::cout тут было бы сохранение значения в переменную класса this. В данном случае никакой «гонки данных» происходить не будет даже в случае многопоточного кода, так как коллбэк будет возвращаться в контекст того класса, где был порожден