Главная страница Случайная страница Разделы сайта АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
💸 Как сделать бизнес проще, а карман толще?
Тот, кто работает в сфере услуг, знает — без ведения записи клиентов никуда. Мало того, что нужно видеть свое раписание, но и напоминать клиентам о визитах тоже.
Проблема в том, что средняя цена по рынку за такой сервис — 800 руб/мес или почти 15 000 руб за год. И это минимальный функционал.
Нашли самый бюджетный и оптимальный вариант: сервис VisitTime.⚡️ Для новых пользователей первый месяц бесплатно. А далее 290 руб/мес, это в 3 раза дешевле аналогов. За эту цену доступен весь функционал: напоминание о визитах, чаевые, предоплаты, общение с клиентами, переносы записей и так далее. ✅ Уйма гибких настроек, которые помогут вам зарабатывать больше и забыть про чувство «что-то мне нужно было сделать». Сомневаетесь? нажмите на текст, запустите чат-бота и убедитесь во всем сами! P. Set_value(res);⇐ ПредыдущаяСтр 28 из 28
} catch (...) { // Ой: не могу получить res p.set_exception(std:: current_exception()); }
Это все хорошо, но как мне получить пару соответствующих друг другу объектов future / promise – один объект в моем потоке, а другой – в каком-то другом? Ну, поскольку объекты future и promise могут перемещаться (но не копироваться), то решить это можно самыми разными способами. Наиболее очевидный подход заключается в следующем: при запуске задачи передать ей объект promise и оставить вызывающему коду соответствующий объект future, куда будет помещен результат. Использование async() является наиболее экстремальным и элегантным способом использования этого подхода. Тип package_task предоставляет простой способ запуска потока для выполнения задачи. В том числе, он заботится об установке объекта future, связанного с соответствующим объектом promise и предоставляет обертку для помещения результата или исключения из задачи в promise. Например: double comp(vector< double> & v) { // упаковываем задачи: // (в качестве задачи мы используем стандартный // метод accumulate() для массива double): packaged_task< double(double*, double*, double)> pt0{ std:: accumulate< double*, double*, double> }; packaged_task< double(double*, double*, double)> pt1{ std:: accumulate< double*, double*, double> }; auto f0 = pt0.get_future(); // получаем future auto f1 = pt1.get_future(); pt0(& v[0], & v[v.size()/2], 0); // запускаем потоки pt1(& v[v.size()/2], & v[size()], 0); return f0.get()+f1.get(); // получаем результаты }
См. также:
std:: async() Метод async(), предназначен для простого запуска задач, является единственной возможностью, которая не утверждена в черновом варианте стандарта. Я ожидаю, что она будет принята в октябре, после переработки двух немного отличающихся предложений. Вот пример того, как программист может подняться над всеми этими непонятными потоками и блокировками в многопоточном программировании. // простой функтор аккумулятора template< class T, class V> struct Accum { T* b; T* e; V val; Accum(T* bb, T* ee, const V& v): b{bb}, e{ee}, val{vv} {} V operator() () { return std:: accumulate(b, e, val); } }; double comp(vector< double> & v) // запускаемнесколько задач, если v содержит // довольно много элементов { if (v.size()< 10000) return std:: accumulate(v.begin(), v.end(), 0.0); auto f0 {async(Accum{& v[0], & v[v.size()/4], 0.0})}; auto f1 {async(Accum{& v[v.size()/4], & v[v.size()/2], 0.0})}; auto f2 {async(Accum{& v[v.size()/2], & v[v.size()*3/4], 0.0})}; auto f3 {async(Accum{& v[v.size()*3/4], & v[v.size()], 0.0})}; return f0.get()+f1.get()+f2.get()+f3.get(); }
Это очень простой способ использования многопоточного программирования (обратите внимание на использования «магических чисел»), но обратите внимание на отсутствие явного использования потоков, блокировок, буферов и т.п. Тип переменных f xопределяется типом возвращаемого значения функции стандартной библиотеки async(), которая возвращает future. В случае необходимости, вызов метода get() объекта типа future ожидает завершения потока. В данном случае, обязанностью метода async() является порождение потоков, а задачей объектов future является вызов join() для ожидания завершения соответствующих потоков. «Простота» является самым важным аспектом дизайна async() / future; тип future может быть использован вручную при работе с потоками, но даже и не думайте использовать async() для запуска задач, выполняющих ввод/вывод, использующих мьютексы или каким-то другим способом взаимодействующих с другими задачами. Идея создания async() аналогична идее, лежащей в основе range-for оператора: предоставить простой механизм обработки самых простых и довольно распространенных случаев, и оставить базовые механизмы для более сложных случаев. Вызывающий код может указать, чтобы метод async() запускал новый поток, использовал любой поток, кроме вызывающего или же запускал задачу в новом потоке, только если async() «считает», что это того стоит. Последний вариант является самым простым с точки зрения пользователя и потенциально самым эффективным ((только) для простых задач). См. также:
|