Программа смены фона рабочего стола
Программа смены фона рабочего стола. При запуске, программа циклически меняет фон рабочего стола: Файл ->Solid Color->Файл ->Solid Color->…

Типизированный язык программирования
Программа смены фона рабочего стола. При запуске, программа циклически меняет фон рабочего стола: Файл ->Solid Color->Файл ->Solid Color->…

Многие наверняка сталкивались с проблемой: смотришь по ТВ спокойный фильм, который прерывается резкой и громкой рекламой; или, например, при общении по ВКС всех собеседников слышно нормально, но у кого-нибудь одного микрофон будет шуметь так, будто он в данный момент находится рядом с двигателем самолета, готовящегося взлетать. Конечно, всегда можно подрегулировать громкость динамиков, но всегда ли это удобно и возможно?
После чтения несколько недавних статей – раз, два, три – и, главным образом, комментариев к ним, задумался о том, а как бы лично мне хотелось чтобы C++ развивался дальше. Результатом этих размышлений и стал данный текст. Признаю, что он больше бы подошел для личного блога, т.к. здесь не более чем праздные фантазии оторванного от мейнстрима провинциала. Но все-таки решил вынести свои несбыточные грезы на широкую публику, уж простите эту нескромность.
Возможно, самым практичным был бы вариант, когда C++ окончательно уходит на обочину и повторяет судьбу COBOL-а – где-то как-то тихо и мирно живет себе за счет многолетнего легаси, которое приносит деньги и которое никто не решается переписать на чем-то модном и молодежном. А новые стандарты не столько пытаются модернизировать язык, сколько поддерживают его на плаву.
Но кажется, что комитет выбрал для C++ совсем другой сценарий развития. Свидетельством чему является включение в стандарт такой странной (на мой деревенский взгляд) штуки, как модули. Раз модули в язык добавили несмотря на то, что это делит и сам язык, и его экосистему, на “до и после” на долгие годы, а то и десятилетия, значит люди из комитета верят, что у C++ эти самые десятилетия бодрого развития и широкого применения есть.
OK, допустим, что цель в том, чтобы C++ счастливо и успешно прожил еще 40 лет, постоянно развиваясь и адаптируясь к новым условиям. Что для этого нужно сделать сейчас? Важный дисклеймер: на мой сугубо субъективный взгляд.

Сидел я значится между двумя ноутбуками, на одном из которых играла музыка. Динамики старые и стерео выдают в неприкрытом моно. Между звуками барабанов и синтезаторов в моей голове прозвучала мысль — «А давай‑ка одновременно включим музыку на двух ноутбуках, получу ли я музыкальное наслаждение?» — Получил это музыкальное наслаждение я аж целых три года назад, тогда же появилась идея оформить сеё чудо в виде приложения, которое бы захватывало системный звук устройства и раздавало бы его на динамики любых других устройств (Компьютеры, планшеты, телефоны…), включая устройство захвата.

Ни Python, ни PyTorch, ни NumPy, … всего 260 строк кода на чистом C++ достаточно, чтобы обучить, оценить и протестировать простой двоичный классификатор, различающий рукописные цифры 0 и 1.

Недавно я опубликовал мнение о фундаментальной экономической модели разработки ПО, которая не способствует (и объективно не должна способствовать) массовому переходу с C/C++ на «безопасные» языки программирования Экономика безопасности кода или почему Rust не нужен.
Но чтобы оставаться честным перед читателями, решил опубликовать и статью-контраргумент с описанием обратной стороны медали, то есть почему C++ всё равно будет рано или поздно заменён, а заодно попробовать разобрать, каким будет новый язык программирования, который неминуемо придёт на смену C++.

Всем привет, это моя первая статья, в рамках которой захотелось поделиться необычным для меня опытом. Возможно, кто-то найдёт здесь для себя что-то полезное. По работе пришлось столкнуться с крайне необычной микросхемой для коммутации высокочастотных (RF) сигналов. Одна проблема – проприетарный интерфейс управления MIPI RFFE. Появился вопрос “А как этим управлять, не имея специализированных средств?”. Ответ узнаем вместе.

У многих из нас есть слабость к маленьким многофункциональным гаджетам. К тем самым коробочкам с мигающими светодиодами, которые покупаются под лозунгом «ну это же мне очень надо!», а потом укоризненно смотрят на тебя с полки. У меня к этой категории относятся «тамагочи для хакеров» Flipper Zero и оранжевый свисток M5StickC Plus2.
С «Флиппером» всё понятно: для классических хакерских шалостей (открывать шлагбаумы и пугать соседей) я его не использую, пару раз клонировал ключи от подъезда да дублировал пропуск на работе. Для меня это стильные настольные часы, токен для аутентификации и крошечная панель мониторинга (я переписал под себя приложение для мониторинга ПК, чтобы выводить на экран загрузку процессора, ОЗУ, видеокарты, состояние сети и прочие метрики).
С M5StickC Plus2 история похожая. Он был куплен по той же причине, по которой айтишники покупают седьмую механическую клавиатуру: потому что штука прикольная. Я покрутил разные прошивки, поигрался с Bruce — швейцарским ножом для устройств M5 — и даже попытался сделать из него такой же экранчик мониторинга, но в отличие от Флиппера, заряда которого хватает на пару дней приёма метрик с ПК через BLE, стик садится почти моментально, да и его экран ощутимо меньше. А потом он предсказуемо перешёл в режим ждуна: лёг на стол и стал ждать своего часа.
Статья объясняет что такое WIC (Windows Imaging Component) и как с ним работать (с примерами), рассчитано для тех кто никогда не слышал, или почти никогда не слышал о WIC. Является переписью того, что написано в MSDN, но: на русском, понятно, кратко.

Существуют решения для анонимного взаимодействия в интернет пространстве, такие как Tor, I2P и Freenet, но они ориентированы на весь интернет и избыточны для простого общения. Их сложность и архитектура могут быть неудобны в условиях ограниченного доступа к сети. Поэтому возникает идея более простой и специализированной системы. XXCore — это лёгкая p2p-архитектура с доверенными узлами, построенная на PipeNet и модифицированном SSU2.

Когда логирование попадает в реальную систему, довольно быстро становится понятно, что это не про API и не про удобство вызова. Это про постоянный компромисс.
С одной стороны, хочется, чтобы система работала максимально быстро: любое логирование — это накладные расходы, и в нормальном режиме его стараются минимизировать. С другой стороны, как только возникает проблема, внезапно оказывается, что либо логов недостаточно, либо они есть, но в таком виде, что восстановить картину происходящего невозможно. В этот момент становится очевидно, что задача логгера — не просто «писать строки» максимально быстро, а помогать удерживать баланс между производительностью и диагностируемостью.
Первая проблема, которая всплывает практически сразу, связана не со скоростью, а со структурой. Лог начинает отражать структуру кода, а не структуру происходящего. Есть бизнес‑логика, есть библиотеки, есть множество параллельных операций, и каждая из них пишет что‑то своё. В итоге лог превращается в поток сообщений, где перемешаны разные задачи, и вместо «обработки конкретного запроса» мы видим просто последовательность вызовов. На небольшом проекте это ещё можно терпеть, но в серверной системе такая картина быстро становится непригодной для анализа.
Естественное желание — привязать лог не к месту вызова, а к самой задаче. Самый прямой путь — передавать контекст через параметры (например, инстанс логгера), но довольно быстро это начинает протекать через весь код и превращается в обязательный шум в сигнатурах. Гораздо более устойчивый подход — привязать контекст к потоку выполнения. В библиотеке logme это делается через thread channel:

Бесплатных IDE для разработки микроконтроллеров не так уж много, а их интерфейс, основанный на Eclipse, вызывает у меня только страдания. В итоге разработка превращается в постоянное переключение с VSCode для редактирования кода в CubeIDE для его сборки и отладки.
Но почему бы не собрать все инструменты в VSCode в едином расширении, заодно подогнав автогенерацию проектов под стиль компании/личные предпочтения? Об и будет моя первая статья. Привет, Хабр!

Если говорить о производительности вне существующих решений в железе, то интуиция будет подсказывать достаточно простую модель выполнения, когда процессор обрабатывает инструкции, а память поставляет данные, и чем быстрее и то и другое, тем быстрее работает программа.
Но процессоры научились выполнять миллиарды операций в секунду, а память наращивает скорость доступа намного медленнее, и разрыв между скоростью вычислений и доступа к данным стал настолько большим, что именно ожидание памяти, превратилось в главный источник потерь производительности.
Ответом на это стало не ускорение памяти, а усложнение самих процессоров, которые перестали быть просто пассивными исполнителями кода и стали решать задачи управления потоком данных: выполнять инструкции вне порядка, переупорядочивать зависимости и на каком‑то этапе подошли к идее спекулятивно исполнять код, который, возможно, вообще не понадобится.
Предсказание ветвлений стало один из ключевых механизмов в этой системе, которая должна была снять часть времени простоя потока вычислений, но если удачное предсказание стало возможностью начать дорогие загрузки заранее и скрыть их латентность, то ошибка предсказания скрывает не только потерянные такты, но и зря использованные ресурсы памяти: шину, буферы загрузки, пропускную способность контроллера и сами кэш‑линии, которые могли бы быть заняты полезными данными.
Именно здесь возникает интересный и неочевидный компромисс, позволяющий с одной стороны, писать branchless‑код и полностью избавиться от ошибок предсказания, а с другой лишающий процессор возможности работать на опережение и запускать доступ к памяти раньше времени. Но в зависимости от того, где находятся данные в памяти выигрывать будет то один, то другой подход.
Если вы собираетесь писать branchless код, надо помнить как именно спекулятивное выполнение и предсказание ветвлений взаимодействуют с подсистемой памяти, потому что «лишняя работа» иногда ускоряет программу, а в некоторых случаях попытка сделать код более «предсказуемым» приводит к обратному эффекту.

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

Привет, Хабр! Меня зовут Aloncie. Пока в моем окружении часто спорят о том, какой язык программирования учить первым, я решил не выбирать легких путей и закопаться в «кишки» системного программирования.
Мой проект Rwal — это CLI-утилита (с перспективой перехода на GUI) для управления обоями, которая должна одинаково хорошо чувствовать себя в разных окружениях: от KDE и GNOME до Windows. В этой статье я подробно разберу архитектуру проекта, работу с D-Bus, интеграцию со стандартами C++20 и то, как я организовал сборку.

Всё началось на второй паре по системному программированию. Нам дали задачу: написать CLI-утилиту для анализа логов - парсить файл, фильтровать записи по уровню ошибок, считать статистику, выводить красиво в консоль. "Ну понятно", - открыл я vim и началось мое долгое приключение...
Неделя. Две. Утилита называлась logz, она умела читать логи nginx и apache, фильтровать по уровню (DEBUG, INFO, WARN, ERROR), по дате, по IP, выводила топ адресов с наибольшим числом ошибок, рисовала простенький bar-chart прямо в терминале через unicode-символы. Только вот я сидел как-то вечером, запустил wc -l main.c - 3147 строк. И смотрел на это число минуты три с таким лицом - O_O.
Сама утилита работала. Но открывая её осознаешь что - это месиво. Одна функция process_file на 400 строк. Сегфолты раз в неделю. Valgrind как лучший друг. И каждый раз когда надо добавить фичу - сначала полчаса вспоминаешь что вообще происходит в коде.
Потом я случайно прочитал пост про Zig на lobste.rs. Заинтересовался и попробовал. Через месяц у меня была та же утилита, но теперь на 1089 строках, которая работала быстрее и не падала.
Тут я понял что вот золотая жила и расскажу о том - зачем Zig, как переписывал, где облажался и что вышло в итоге.

Прочитал статью Параллелизм с общим состоянием в Rust и обратил внимание, что её общий смысл можно выразить известной фразой: “делай как нужно, а как не нужно, делать не нужно”. Другими словами, это точно такой же совет, какой можно дать разработчику любого другого языка программирования, например С++.
И решил не продолжать дискуссию в комментариях, а написать отдельную статью с кратким описанием фундаментальной экономической модели разработки ПО, которая не способствует (и объективно не должно способствовать) массовому переходу с C/C++ на «безопасные» альтернативы. Так как из-за особенностей распределения затрат у разработчика ПО отсутствует экономическая мотивация к полному устранению ошибок, и как следствие - к переходу на использование «безопасных» языков программирования.

Привет! На связи Антон Полухин из Техплатформы Городских сервисов Яндекса. На днях в Кройдоне состоялась встреча международного комитета по стандартизации языка программирования C++, в которой я принимал активное участие. В этот раз (как и в прошлый), всё внимание было сосредоточено на C++26 и… теперь он готов! Осталось пройти формальные этапы в вышестоящих инстанциях ISO, и мы получим C++26 который заслужили. В нём будут:
• reflection,
• контракты,
• SIMD,
• линейная алгебра,
• расширенные возможности сonstexpr,
• hardening,
• Hazard Pointer и RCU,
• #embed,
• executors,
• и многие другие полезные вещи.
Кратко расскажу о себе и о том, зачем возникла необходимость в подобном. Я более десяти лет пишу приложения под Android, около 5 лет под IOS, и сейчас переношу свои наработки под десктопы. Приложения мои предназначены для сисадминов, это SSH клиент, сетевые сканеры и тд. В общем, самое сложное — не сам интерфейс, а то, что под капотом. Когда я лишь начинал, я думал, что остановлюсь на платформе Android и стал пилить все на Java. Но затем осознал свою ошибку и исправил ее. На данный момент все мои приложения состоят из двух частей: общего для всех систем ядра на С++ и платформозависимого интерфейса, написанного на Java/Swift/C++ в зависимости от системы.
Оговорюсь сразу, эта статья будет лишь своего рода вступлением. Я покажу, как работать с объектно‑ориентированным кодом на C++ в Java оболочке (в JNI нам доступен экспорт С функций). Инициализировать объект, делать из него вызовы, удалять, при этом имея аналогичный класс в оболочке, будто бы наш код был написан на Java. Задача эта не слишком сложная, но прежде чем опытные прогеры закрыли эту статью, я оговорюсь, что в следующей части мы уже будем работать с каллбэками — вызовами Java листенеров из нашего С++ кода, а вот это уже задача совсем нетривиальная, требующая понимания работы JNI и Dalvik. Но обо всем по порядку.
Итак, у нас есть некий CPP класс и Java оболочка. Через JNI мы можем вызывать только С‑функции, то есть не объектный код. Так как же нам работать с ООП? Главная проблема — не столько вызовы, сколько хранение адреса объекта нативного класса. Лично для себя я нашел решение — хранить его в Java классе, как long. То есть, у нас получается приблизительно такой код:
Stratum 1 NTP-сервер на Raspberry Pi в 2025 году: DCF77 + GPS/PPS, chrony, libgpiod v2, когда все туториалы по «точному времени на Raspberry Pi» сломаны на современных системах. Разбираю почему — и показываю как сделать правильно.