8 марта уже на горизонте. Цветы — это база. А что добавим к релизу?
Если хочется сделать красивый апгрейд праздника, присмотритесь к дизайнерским игрушкам от Super Toys!
Это не только милый сувенир, но и стильные арт-объекты от современных художников и культовых брендов, которые украсят её рабочий стол или полку и будут напоминать о вашем вкусе и внимании гораздо дольше, чем праздничные сторис.
Мы собрали специальную праздничную подборку — чтобы вы закрыли задачу по подарку быстро и красиво!
Прокачайте 8 марта до версии Pro!
Реклама. ООО "НОВЫЕ МЕДИА". ИНН 7813407148. erid: 2W5zFHxq257
Если хочется сделать красивый апгрейд праздника, присмотритесь к дизайнерским игрушкам от Super Toys!
Это не только милый сувенир, но и стильные арт-объекты от современных художников и культовых брендов, которые украсят её рабочий стол или полку и будут напоминать о вашем вкусе и внимании гораздо дольше, чем праздничные сторис.
Мы собрали специальную праздничную подборку — чтобы вы закрыли задачу по подарку быстро и красиво!
Прокачайте 8 марта до версии Pro!
Реклама. ООО "НОВЫЕ МЕДИА". ИНН 7813407148. erid: 2W5zFHxq257
👍3👎2❤1
Мини-пул потоков на std::jthread
Создадим простой пул, который принимает лямбды, параллельно их выполняет и авто-join-ит потоки при выходе из области.
Храним очередь задач, мьютекс, условную переменную и вектор рабочих потоков. Флаг
Конструктор порождает
Деструктор ставит флаг
🔥 Чистый стандарт C++20 — ни Boost, ни сторонних либ!
📣 C++ Ready | #практика
Создадим простой пул, который принимает лямбды, параллельно их выполняет и авто-join-ит потоки при выходе из области.
class ThreadPool {
std::queue<std::function<void()>> jobs; // очередь заданий
std::mutex m;
std::condition_variable cv;
bool stop = false;
std::vector<std::jthread> workers; // jthread = RAII-joinХраним очередь задач, мьютекс, условную переменную и вектор рабочих потоков. Флаг
stop сигнализирует о завершении.public:
ThreadPool(size_t n = std::thread::hardware_concurrency()) {
for (size_t i = 0; i < n; ++i)
workers.emplace_back([this](std::stop_token st) {
while (!st.stop_requested()) {
std::function<void()> job;
{ std::unique_lock lk(m);
cv.wait(lk, [this]{ return stop || !jobs.empty(); });
if (stop && jobs.empty()) return;
job = std::move(jobs.front()); jobs.pop();
}
job(); // выполняем задачу
}
});
}
Конструктор порождает
n потоков. Каждый рабочий ждёт, пока в очереди появится задача, — или пока пулу не придёт сигнал остановиться.template<typename F>
void enqueue(F&& f) {
{ std::lock_guard lk(m); jobs.emplace(std::forward<F>(f)); }
cv.notify_one(); // будим один поток
}
enqueue кладёт новую лямбду в очередь и будит спящего воркера. ~ThreadPool() {
{ std::lock_guard lk(m); stop = true; }
cv.notify_all(); // будим всех для выхода
}
};Деструктор ставит флаг
stop, будит все потоки, а std::jthread автоматически дожидается их завершения.int main() {
ThreadPool pool(4); // 4 рабочих потока
for (int i = 0; i < 8; ++i)
pool.enqueue([i]{ std::printf("job %d\n", i); });
} // ← при выходе pool завершит все задачиPlease open Telegram to view this post
VIEW IN TELEGRAM
👍15🔥10❤5
Например, HTTP передаёт данные в открытом виде, без шифрования. HTTPS работает поверх TLS и защищает соединение: выполняется проверка сертификата, обмен ключами и дальнейшая передача данных в зашифрованном виде.
На картинке — ключевые этапы установления соединения.
Сохрани, чтобы не забыть!
Please open Telegram to view this post
VIEW IN TELEGRAM
❤21🔥9👍5
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥23👍7❤3🤝2
This media is not supported in your browser
VIEW IN TELEGRAM
Если тебе сложно понять алгоритмы по учебникам — этот ресурс решает проблему. Автор объясняет графы, геометрию, деревья, меши из геймдева через понятные визуализации и интерактивы. Сложные идеи здесь раскладываются на простые шаги.
Please open Telegram to view this post
VIEW IN TELEGRAM
🤝13❤10👍5
Почему std::shared_ptr иногда тормозит даже без потоков?
На вид это просто умный указатель. Кажется, что раз всё в одном потоке — накладных расходов почти нет.
Но у
Из-за этого можно получить просадку там, где её не ждёшь: циклы, коллбеки, мелкие функции.
Если владение не шарится — лучше
🔥 В hot path не передавай
📣 C++ Ready | #совет
На вид это просто умный указатель. Кажется, что раз всё в одном потоке — накладных расходов почти нет.
Но у
shared_ptr есть счётчик ссылок в control block. Когда ты передаёшь shared_ptr по значению, на входе и выходе функции делается refcount++/refcount-- (обычно атомарно). В горячем коде это превращается в лишнюю работу, хотя логически ты “просто передал указатель”.Из-за этого можно получить просадку там, где её не ждёшь: циклы, коллбеки, мелкие функции.
Если владение не шарится — лучше
unique_ptr или значение. Если шаринг нужен — просто не копируй shared_ptr без причины.void log(std::shared_ptr<Foo> p); // копия -> refcount++/--
void hot(const std::shared_ptr<Foo>& p) {
for (int i = 0; i < 1'000'000; ++i)
log(p); // лучше: log(const std::shared_ptr<Foo>&)
}
shared_ptr по значению — используй const std::shared_ptr<T>& (или unique_ptr, если шаринга нет).Please open Telegram to view this post
VIEW IN TELEGRAM
🔥15❤7👍4
Атомарный доступ к полю без изменения его типа!
Иногда нужно синхронизировать доступ к полю структуры, но менять его тип на
Объявим структуру и создадим атомарную ссылку на поле:
Теперь можно безопасно работать с полем из нескольких потоков:
🔥
📣 C++ Ready | #практика
Иногда нужно синхронизировать доступ к полю структуры, но менять его тип на
std::atomic<T> невозможно — например, он используется сторонним API или загружается из сериализованного формата. В таких случаях поможет std::atomic_ref из C++20.Объявим структуру и создадим атомарную ссылку на поле:
#include <atomic>
struct Data {
int counter = 0;
};
Data d;
std::atomic_ref<int> a(d.counter);
Теперь можно безопасно работать с полем из нескольких потоков:
#include <thread>
std::jthread t1([&]{ a++; });
std::jthread t2([&]{ a += 2; });
std::atomic_ref делает атомарными любые переменные — удобно, когда нельзя менять исходные типы, но нужна потокобезопасность.Please open Telegram to view this post
VIEW IN TELEGRAM
🔥16❤5👍4
В этой статье:
• Как устроен разбор HTTP-запросов и формирование корректных ответов.
• Как реализовать роутинг, раздачу статики и работу с конфигом сервера.
• Как сделать неблокирующий ввод-вывод и обработку нескольких клиентов.🔊 Продолжай читать по ссылке!
Please open Telegram to view this post
VIEW IN TELEGRAM
❤10🔥6👍3
Когда обработчиков для std::variant становится много, код может расползаться, а паттерн overload собирает все ветки в одном месте и делает чтение проще.
В этом гайде:
• Покажем минимальный helper overload, который объединяет несколько лямбд;
• Разберем пример с разными типами в std::variant, чтобы увидеть структуру обработчика;
• Применим тот же прием к обработке событий, где важна явность каждой ветки.
После этого вы сможете писать обработчики visit компактно и при этом сохранять строгую типизацию.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥21❤9👍4🤝1
В этой статье:
• Как зарождался OpenCV и какую роль в этом сыграли люди из Intel.• Почему развитие проекта во многом определяли случайности, энтузиазм и удачные решения.• Как OpenCV смог вырасти в инструмент мирового уровня и получить признание сообщества.🔊 Продолжай читать по habr!
Please open Telegram to view this post
VIEW IN TELEGRAM
❤9🔥4👍3
Почему unordered_map может быть медленнее map?
Потому что в реальном коде все сложнее, чем просто
На бумаге
У
Из-за этого код в духе:
не всегда оказывается быстрее, чем:
То есть контейнер “быстрее по учебнику” может проиграть в проде.
🔥 Для важного кода контейнер лучше мерить, а не выбирать по мифу про O(1).
📣 C++ Ready | #совет
Потому что в реальном коде все сложнее, чем просто
O(1) против O(log N).На бумаге
unordered_map выглядит очевидным победителем. Но в жизни у него есть цена: хеширование ключа, коллизии, rehash и более хаотичный доступ к памяти.У
map асимптотика хуже, но иногда она ведет себя стабильнее. Особенно если важны предсказуемость, порядок элементов или нормальная locality на конкретных данных.Из-за этого код в духе:
sum += um["user_" + std::to_string(i)];
не всегда оказывается быстрее, чем:
sum += m["user_" + std::to_string(i)];
То есть контейнер “быстрее по учебнику” может проиграть в проде.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12❤7👍6