Как стать автором
Обновить
0
0

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

Отправить сообщение
Владимир Милов вроде бы говорил, что советское правительство таки отпустило оптовые цены, но не отпустило розничные, соответственно магазины ничего не продавали, так как нет смысла — фиксированная розничная цена была меньше, чем закупочная оптовая. Подтверждений этой инфы в интернете не так много но например вот
Ну, размер проекта понятие относительное.
Кто-то считает LLVM и Qt большими проектами, а кто-то — маленькими=)
Просто когда у вас пара терабайт кода, там начинаются пляски с бубнами вокруг системы сборки/системы контроля версий и прочего — догадываться что изначально имелось ввиду под «большим проектом» — дело неблагодарное.
Вообще, интересно сравнить один и тот же проект на разных системах сборки, но, к сожалению, это редко возможно — никто не хочет поддерживать зоопарк билдсистем. Я сравнивал сборку QtCreator с qbs/cmake — full build быстрее у qbs (~2.5 минуты разницы), null build быстрее у cmake+ninja (аж в 2 раза — 1.1 секунды против 2). Конфигурация у qbs чуть медленнее (к сожалению, данные не сохранил).

Порт на QmlEngine идет достаточно успешно — резолвер проекта полностью портирован, ломающих изменений вроде бы не будет. К следующему релизу не успеем, но в целом всё выглядит многообещающе.
Потом, QtScript добавлен как сабмодуль уже много лет, его тоже можно портировать на Qt6 — там не такие большие изменения требуются (в самой Qbs даже чуть больше поправить надо), я проверял.
Простите, я имел ввиду тот suspendedWaiter.load() что в notify(). notify() и await_suspend() вызываются же в разных потоках?
Более детально, event1 посылает уведомление до того как receiverThread1 был запущен.

Я не понимаю чем это гарантируется. Также я не понимаю почему нет рейса между if (event.notified), suspendedWaiter.load() и event.suspendedWaiter.store(this)
Что-то у вас всё в кучу намешано.
Отвечу на ту тему, про которую я изначально писал.
Да, у богатого Буратины в Штатах больше шансов, чем у бедного. Но при этом два одинаково богатых Буратины имеют одинаковые шансы в суде как и два одинаково бедных негра. В этом смысле закон работает для всех одинаково. Есть четкие и понятные правила — если у вас есть деньги на адвоката, то вам лучше, нет денег — хуже, но это заранее известно и судье не звонят из Администрации с наказом «этот подсудимый особенный».
В РФ всё не так. Вы можете быть очень богатым человеком, наверное вы можете думать, что у вас есть связи, пока вас не посадят на десяточку, а вашу нефтяную компанию не отдадут человеку, носящему портфель за президентом. Ну просто потому что у вас язык слишком длинный. Или компания слишком дорогая.
В РФ не действуют все эти «западные» ценности типа хорошего адвоката. Я даже больше скажу — вы занести взятку судье не всегда можете, телефонное право тут имеет приоритет над вашими бабками.
А эти самые правила, как и вероятность попасть в немилость, меняются по желанию левой пятки какого-то чиновника/силовика/хрена с горы.
Я конечно понимаю, что хочется верить в «обратный карго-культ» ( Шульман), что «везде всё одинаково», но далеко не везде и не одинаково. Что не отменяет факта что США та ещё помойка, но это другая помойка с совершенно другими проблемами.
Приезжайте в РФ, поживите несколько годиков, ощутите на себе новостную повестку, а то что же вы всё из Латвии-то смотрите?
Обычно законы пишут элиты для того чтобы они соблюдались самими элитами и потом уже обобщаются на всё общество. В РФ же всё не так — илита живет по своим законам («по понятиям», если угодно), а обычные законы существуют для того, чтобы ограничивать плебс в правах (как ваш пример со свободой собраний). Получается, что правила игры размыты — одни правила для одних, другие для других, да еще и эти вторые правила нигде не формализованы. А те законы, которые формализованы, формализованы настолько расплывчато, что их можно повернуть как угодно. Почему вы выбираете какую-то одну трактовку («митинг надо разрешать»), удобную вашему мирку? Мне вот удобнее считать что порядок уведомления о митинге носит уведомительный характер, даже КС со мной согласен.
А по «понятиям» вообще ничего не надо уведомлять — ведь они не описаны нигде. Взял да пришел с посонами потусить где захотел.
Таски, промисы и прочее.
Это всё выглядит как мануал для написания куска стандартной библиотеки, а не что-то готовое к продакшну.
Я вот его не понимаю, неужели предполагается, что мы должны писать этот бойлерплейт? Или это будет добавлено в мифическую рантайм-библиотеку корутин в будущем?
Я на это уже ответил — я не знаю причин, почему именно этот пример не работал бы с volatile. Но он и без volatile может работать (у меня весь проект на работе такой) — можно проверить disasm что там нет неожиданностей.
Проблема x86 именно в том что там есть из коробки многие базовые вещи, предоставляемые атомиками — это и отсутствие reorder'а и когерентность кешей — ваш lock-free алгоритм может работать даже если написан неверно или вообще без атомиков.
От примитивов синхронизации нужно несколько вещей
1. отсутствие оптимизаций компилятора (как пример выше)
2. отсутствие оптимизаций процессора (например, перестановка операций в рантайме)
3. неделимость (атомарность) самой операции.
4. что-то еще забыл?

volatile помогает только с пунктом 1, но одного этого мало. В данном примере его, возможно, и достаточно (но стандарт С++ говорит, что нет).
Пример с relaxed и пунктом 3 подробно разобран в статье на примере инкремента. Это второй юзкейз relaxed, я не стал про него потому что про это уже написали до меня весьма подробно.
Атомики/мьютексы обладают всеми тремя пунктами требований, volatile — только одним из них.
relaxed нужен для того чтобы подсказать компилятору\процессору что вот эта переменная (потенциально) используется для синхронизации.
без нее код типа
bool done = false; //global static
void doWork() {
while (!done)
    foo();
}


может быть соптимизирован в
bool done = false; //global static
void doWork() {
if (done)
    return;
while (true)
    foo();
}


Обусловлено это тем что компилятор волен предполагать что переменная done не меняется в _этом_ потоке (например, если он сможет это доказать, заинлайнив foo), а значит оба варианта эквивалентны.
На практике я такого поведения не встречал (компилятору сложно доказать утверждение выше) и любой sane компилятор так делать не будет, но насколько я знаю, никто ему это не запрещает делать (привет, то самое UB). Миф про volatile же не на ровном месте появился.
На самом деле, думать об атомиках в терминах кэшей достаточно бесполезно. Можно (условно) считать что кэши процессора всегда когерентны — если вы записали в ячейку памяти, то другие ядра это увидят. Проблема в том что помимо кешей есть и другие уровни абстракции (буфер записи в кеш) и регистры процессора, которые не обязаны быть когерентными. Гадать, попало ваше значение в кэш или ещё находится в регистре — занятие неблагодарное, не надо об этом думать=)

Основная проблема не в том когда данные попадут в память (в кэш, в оперативку), а в видимом порядке действий — компилятор/процессор вольны переставлять (независимые по данным инструкции) как им покажется удобным. У меня на работе код изобилует примерами типа 3 (безо всяких атомиков) — люди ничего не слышали про reordering и думают — ну раз я записал в bool ready true, то значит могу читать данные из другого потока (но нет).

Атомики решают проблему на более высоком уровне — они служат барьерами памяти — если есть разделяемый доступ, то обязательно нужен (какой-то) атомик или другой примитив синхронизации (мьютекс, семафор). Если барьера памяти нет, то это UB. Возможно на вашем x86_64 все будет работать потому что это strong-ordered архитектура и без каких-либо атомиков, но по стандарту — это UB, этот код не переносим.

О механике acquire/release так же удобно думать высокоуровнево — когда вам нужен ресурс, вы захватываете его через «acquire», когда закончили — отпускаете с «release».

Я не устаю рекомендовать цикл статей kixmax про lock-free программирование, там есть ответы на ваши вопросы.
На самом деле, интереснее каноничный пример с синглтоном:
static Singleton* singleton = nullptr;
static std::mutex mtx;
 
Singleton *instance() {
	if (singleton ) // early return to avoid touching mutex every call
		return singleton;
 
	std::unique_lock l(mtx); // `mutex` locks here (acquire memory)
	if (!singleton)
		singleton = new Singleton();
        return singleton;
	// `mutex` unlocks here (release memory)
}


Казалось бы, тут всё хорошо? Но нет, Александреску в своей статье пишет что всё плохо.
singleton = new Singleton();

может развернуться в что-то типа такого

// выделили память и записали указатель,
singleton = (Singleton*)malloc(sizeof(Singleton)); 
// если второй тред прочитает указатель в этом месте, то всё упадет
// а вот теперь создали объект (тут еще куча операций)
new (singleton) Singleton();

Мы же хотим что-то типа такого

auto tmp = (Singleton*)malloc(sizeof(Singleton)); // выделили память
new (tmp) Singleton(); // создали объект
singleton = tmp; // записали указатель

Но, понятное дело, гарантий что будет выбран вариант 2 нам никто не дает (скорее всего, не будет, потому что это медленнее). Если же руками написать этот код, то компилятор также может соптимизировать в вариант 1.
К счастью, начиная с С++11 не должна больше болеть голова о синглтонах=)
Да, я неправильно выразился, должно быть «Вызов метода от nullptr это UB. А также, UB — это проверять this на nullptr.» Никогда особо не умел связно писать тексты=(
При том, что вызов невиртуального метода для NULL — совершенно нормальная с точки зрения компилятора вещь без всякого криминала — ну будет неявный параметр (this) равен NULL и что? Код внутри метода может корректно обрабатывать такие ситуации.


Вызов метода от nullptr это UB. Точнее, UB — это проверять this на nullptr. В теории, можно написать метод, который this не проверяет и не использует, как в примере в статье — и это будет работать. Но зачем вам метод класса который не использует this, сделайте его static.
Теперь, собственно, почему проверка this это UB. Рассмотрим пример
struct A 
{
    static inline int globalInt = 0;
    int localInt = 0;
    int foo() { if (!this) return globalInt; else return localInt; }
    // сеттер не нужен для понимания идеи но пусть будет для полноты
    void setFoo(int i) { if (!this) globalInt = i; else localInt = i; }
};

вот так всё работает
A *a = nullptr;
int i = a->foo();


Усложним пример, добавим немного наследования
class B { int i{0}; int j{0}; };
class С : public B, public A {};


И попробуем сделать тоже самое
C *c = nullptr;
int i = c->foo();

Упс, теперь this для базового класса A — это nullptr + sizeof(B). Немного не то, что ожидалось
Ну это зависит от коде стайла, нет? Я видел кодовые базы, где интерфейс звался SomeCoolManager а реализация — SomeCoolManagerImpl (или SomeCoolManagerStub в тестах). В целом, здесь префикс I не нужен так как по всему коду используется только первый, а Impl — только в файле реализации.
Если он (представитель власти) нарушает Закон, превышает свои полномочия, подай жалобу в суд, прокуратуру, воспользуйся цивилизованными методами, а если гражданин решил применить свою силу против силовика, то пусть будет готов ответить за свои действия, т.е. получить силовой ответ.

Я как-то подавал в прокуратуру жалобу на ментов, которые вымогали у меня взятку. Через год после подачи жалобы мне позвонила приятная девушка из прокуратуры и спросила почему я так поздно спохватился. Объяснил, конечно, что я не верблюд, но осадочек остался.
И в данном случае мы имеем на 1 вещественное (айфон, который ты не можешь себе позволить) — аж 5 даже не вторичных услуги.

Это потому что 5 айфонов просто не нужно. Вам не нужно производить еще больше еды — ее и так полно и она дешевая (если мы про Штаты), вам не нужно шить еще больше джинс, вам не нужно еще больше автомобилей. При этом — да, те, кто не попал в реальный сектор экономики, тоже хотят работать (не только банально кушать, но и самореализовываться), поэтому вам нужны все эти «эфемерные» рабочие места (в кавычках потому что прибыль вполне реальна). Альтернатива — посадить эти 80% «лишних людей» на пособие по безработице — ну в целом тоже подход, не уверен, правда, что он понравится людям.
продавая услуги друг дружке и этим — накачивая «метрики» и ВВП

Вы так пишите, как будто это что-то плохое. Доля сферы услуг в экономике США — порядка 80%, Гонконг — 90%. Нидерланды — 74%.
Времена, когда экономика измерялась количеством истребителей или количеством тонн добытого угля, давно прошли.

Информация

В рейтинге
Не участвует
Откуда
Den Haag, Zuid-Holland, Нидерланды
Дата рождения
Зарегистрирован
Активность