Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[44.210.120.182] |
|
Страницы: (4) 1 2 [3] 4 все ( Перейти к последнему сообщению ) |
Сообщ.
#31
,
|
|
|
Цитата JoeUser @ Если слип-задержку не раскоментить - как жрала прога 17% CPU, так и жрет. Это сразу было видно по твоему коду. Но я проверил на всяк случай: Потому что у тебя в цикле нет мониторинга чего либо, у тебя там выполняются конкретные действия, а не "мониторит состояние фискального аппарата". Вот ежели бы тебе нужно было мониторить папку на наличие в ней например какого то файла(появился - что то сделать), а до этого момента просто тупо цикл с проверкой - вот тогда это был бы мониторинг. Цитата JoeUser @ Вот тут: CollapsedWrap disabledLine numbers off if (std::filesystem::exists(FileName)) И как это условие связано с твоими флагами? |
Сообщ.
#32
,
|
|
|
В винде точно есть, но не помню и искать лень. Для FreeBSD вроде запилили libinotify. Про OSX не в курсе. Добавлено Цитата Wound @ И как это условие связано с твоими флагами? Киля, спасибо за беседу! |
Сообщ.
#33
,
|
|
|
Цитата JoeUser @ Вот тут: CollapsedWrap disabledLine numbers off if (std::filesystem::exists(FileName)) Если тебе нужно конкретно файл мониторить, то в принципе тебе выше написали решение: #include <filesystem> #include <iostream> #include <string> #include <thread> #include <atomic> #include <condition_variable> using namespace std::chrono_literals; std::atomic<bool> BreakFlag = ATOMIC_FLAG_INIT; std::atomic<bool> TerminateFlag = ATOMIC_FLAG_INIT; std::string FileName = "C://Temp//helloworld.txt"; std::condition_variable cv; std::mutex cv_m; void ThreadFunc() { do { if (BreakFlag) break; try { std::unique_lock<std::mutex> lk(cv_m); if (cv.wait_for(lk, std::chrono::seconds(1), [=]() {return std::filesystem::exists(FileName); })) { std::filesystem::remove(FileName); cv.notify_one(); } } catch (...) {} // std::this_thread::sleep_for(1ms); // Если не раскоментировать - будет жесть, 17-20% жрет CPU!!! } while (true); TerminateFlag = true; } int main() { std::string str; std::thread Thread(ThreadFunc); Thread.detach(); std::cout << "Type \"Exit\" to exit..." << std::endl; do { std::cin >> str; } while (str != "Exit"); BreakFlag = true; while (!TerminateFlag) std::this_thread::yield(); std::cout << "Done." << std::endl; return 0; } Но это тупо. Потому как у тебя нечего оповещать. Добавлено Если тебе нужно конкретно это условие мониторить, то ты можешь написать класс на основе шаблона Observer, и не выносить мозг себе и людям. Добавлено Цитата JoeUser @ Киля, спасибо за беседу! Ааа, я понял. Ну и иди в баню. censored Пишешь одно, имея ввиду другое, потом еще фыркаешь. Я это запомню. Давай досвидания. |
Сообщ.
#34
,
|
|
|
У мну жсм-шлюз читает/пишет смс-ки в/на ком-порт, достаточно |
Сообщ.
#35
,
|
|
|
Цитата JoeUser @ Они тут по факту не нужны. Но если очень хочется, то можно. Очень хочется – это если хочешь один раз написать и не париться. На WinAPI множественные события ждутся элементарным WaitForMultipleObjects, которая тебе сразу и вернёт тот объект, который отнотифил. Очень удобно. Я бы хотел подобного в std, но коли его нет, можно написать самому: собираешь контейнер предикатов и ожидаешь по нужной комбинации условий, пока не сработают; выходишь с возвратом кортежа результатов предикатов, вызывающий пусть сам анализирует.Перепишите мне с мьютексами, семафорами, или condition_variable чтобы стало лучше/правильнее. И что именно станет правильнее и лучше? Конкретно в твоём примере на cv имеет смысл завести лишь BreakEvent. Маловато, проще явно опрашивать. |
Сообщ.
#36
,
|
|
|
Цитата Qraizer @ Они тут по факту не нужны. Но если очень хочется, то можно. В том то и дело, что Gonarh тут правильно упомянул Бритву Оккамы - если профита в данном случае нет, значит нафик и не нужно. Цитата Qraizer @ На WinAPI множественные события ждутся элементарным WaitForMultipleObjects, которая тебе сразу и вернёт тот объект, который отнотифил. Очень удобно. Я бы хотел подобного в std Да я в курсе. И в *nix подобного очень не хватает, всякие там libevent + inotify + fsnotify запиливают, чтобы можно было реально засыпать на INFINITY время, но мочь всеж проснуться, а не дергать отдельные флаги или мьютексы. Цитата Qraizer @ Конкретно в твоём примере на cv имеет смысл завести лишь BreakEvent. Маловато, проще явно опрашивать. Да нет - не "имеет смысл", а "можно сделать". Но лучше не делать, ибо сам ответил - "проще опрашивать". |
Сообщ.
#37
,
|
|
|
Цитата Qraizer @ Я бы хотел подобного в std Этого и не будет никогда. По крайней мере если коренным образом не определят, что для обеспечения многозадачности С++ - операционная система должна обеспечивать событийную модель взаимодействия. ИМХО, нереально такое ждать. Смысл же WaitForSingleObject/WaitForMultipleObjects в чем? Ядро ОС приостанавливает поток до наступления "одного/одного из" событий (ну или если указано не бесконечное время ожидания) и не отдает ему управление (не ставит в очередь на получение квантов времени). Что мы имеем с std::this_thread::sleep_for? Ядро ОС усыпляет безусловно поток (не ставит в очередь на получение квантов времени) на единицу времени. А что имеем с std::this_thread::yield? Поток вычисления ядром ОС перебрасывается в конец очереди ожидания за получением своего кванта вычислений. И именно ядро усыпляет и пробуждает потоки. И С++ тут никак на этот механизм не может повлиять. Плюс ко всему в последних двух случаях (моей проги) периодически дергается проверка атомарного флага или мьютекса. И если поток не уcыплять - вот тут и ненужные вычисления , ну и бессмысленная загрузка CPU. |
Сообщ.
#38
,
|
|
|
Смысл yield-а в том, чтобы, имея постоянную полезную работу, время от времени проталкивать фоновые процессы, если они есть. Если у тебя нет полезной работы, а пуллинг – это не полезная работа, это её ожидание, – yield не подходит идеологически.
Цитата JoeUser @ Я бы не был так категоричен. Его можно создать на имеющихся примитивах, притом что архитектурно его спроектировать не так-то просто, поэтому и нет пока, ибо комитет просто не хочет садиться в лужу очередной раз, как это уже случалось из-за непродуманной архитектуры библиотечной фичи. Реализовать полный аналог WaitForMultipleObjects() сложно, и ещё сложнее сделать этот механизм удобным и универсальным. Но конкретно ты конкретно в твоём приложении легко это сделаешь в частном порядке, не затратив существенных усилий.Этого и не будет никогда. Добавлено Например. Если ожидать "любого из" объектов, то их надо опрашивать одновременно и тут же, как только, захватывать освободившийся. И всё это атомарно. Последнее условие непросто соблюсти, нельзя их опрашивать тупо по очереди, и захватывать первый попавшийся, будет race condition из-за того, что другой поток может быть позади тебя на пару объектов, и у него другой их набор, да ещё и на другом условии их комбинирования. Если нужно ждать "всех сразу", то последовательно тоже нельзя опрашивать и захватывать, будет dead lock по тем же причинам. Обеспечить атомарность можно, только имея контроль над сущностями, а не их представлениями, что вне ядра подсистемы синхронизации, типа как в винды, невозможно, т.к. изначально объекты синхронизации друг с другом никакими условиями не связаны и разными нитками запросто могут использоваться в разных комбинациях и даже поодиночке. |
Сообщ.
#39
,
|
|
|
Цитата JoeUser @ Так вот первую функцию я не могу использовать по одной простой причине - пока она бесконечно висит я не могу завершить поток нормальным способом если вдруг мне это надо. Поэтому я использую вторую функцию с указанием тайм аута. Нет данных - пошла очередная итерация цикла. А вот в ней я уже могу анализировать BreakFlag. Если увижу что взведен - выхожу из цикла и завершаю поток. Раз у тебя нет в арсенале неблокирующих функций, то никакие cv тебе не помогут. Читай с небольшим таймаутом и в каждой итерации проверяй флаг выхода, лучше особо ничего не сделаешь. Из очевидных минусов: необходимость доп. потока и завершение будет с задержкой (обычно это не критично). Цитата JoeUser @ Я должен осуществлять другую операцию в потоке - вместо interception_wait_with_timeout ... что нибудь типа std::filesystem::exists("helloworld.txt"). И если файл найден - удалять. Делать пока поток не будет прерван. Если sleep в цикл не поставлю - "комп через час-два закипит"? Простое решение - проверять со sleep'ом в цикле. Более сложное - использовать события ОС об изменения файла/каталога в асинхронном варианте. В Виндах это, например, ReadDirectoryChangesW. |
Сообщ.
#40
,
|
|
|
Цитата Qraizer @ что вне ядра подсистемы синхронизации, типа как в винды, невозможно Ключевые слова: "вне ядра невозможно". Можно написать кучу велосипедов, но пока нет доступа к ядерному планировщику потоков - это будет, имхо, только имитация. И да, в Линухах, *BSD-системах ядро открытое, там в принципе попытаться можно. Как? Я не в теме. Но думаю одним лишь загружаемым модулем не обойтись, как догадка. shm, ты все правильно написал. Я так и реализовал, и других альтернатив не вижу. Хотя в моем случае - ожидание завершения потока, в принципе, можно зацепить на мьютекс. Но это ну совсем не критично в моем варианте. У меня это скорее дань к подходу к работе с внешними процессами, т.к. у меня выход из цикла - это по сути пару машиннх команд до завершения фонового потока. Цитата shm @ Более сложное - использовать события ОС об изменения файла/каталога в асинхронном варианте. Да, я бегло читал про возможности часто-используемых ОС-ей. В венде и линухах можно, во фряхе ... еще мутят (инфа от 2014 года), может уже и намутили. |
Сообщ.
#41
,
|
|
|
Цитата Qraizer @ Я бы не был так категоричен. То, что ты предлагаешь, в некоторых ЯП есть - это зеленые потоки. Но реализовать без языковой VM - это, по-сути, писать часть своей VM. Если бы комитет за это взялся - я бы просто офигел. Надеюсь С++ не скатится в недо си-шарпо-джавы. |
Сообщ.
#42
,
|
|
|
Цитата JoeUser @ .. И в *nix подобного очень не хватает, всякие там libevent + inotify + fsnotify запиливают, Имеется select, poll,epoll. Выбирай по вкусу. |
Сообщ.
#43
,
|
|
|
Цитата ЫукпШ @ Имеется select, poll,epoll. Не "локальные" решения, а указанные мною либы претендуют на кроссплатформенные. К примеру: Цитата Currently, libevent supports /dev/poll, kqueue(2), event ports, POSIX select(2), Windows select(), poll(2), and epoll(4). The internal event mechanism is completely independent of the exposed event API, and a simple update of libevent can provide new functionality without having to redesign the applications. As a result, Libevent allows for portable application development and provides the most scalable event notification mechanism available on an operating system. Libevent can also be used for multi-threaded applications, either by isolating each event_base so that only a single thread accesses it, or by locked access to a single shared event_base. Libevent should compile on Linux, *BSD, Mac OS X, Solaris, Windows, and more. |
Сообщ.
#44
,
|
|
|
Цитата JoeUser @ но пока нет доступа к ядерному планировщику потоков - это будет, имхо, только имитация Дело не сколько в доступе к планировщику, а в обработке аппаратных прерываний. Добавлено Цитата JoeUser @ Хотя в моем случае - ожидание завершения потока, в принципе, можно зацепить на мьютекс. И что тебе это даст? |
Сообщ.
#45
,
|
|
|
Цитата shm @ И что тебе это даст? Временное примирение с Килей! Добавлено Цитата shm @ Дело не сколько в доступе к планировщику, а в обработке аппаратных прерываний. А я не согласен! Ну "захватил ты ресурс" (начал обрабатывать прерываание) , а если системный планировщик потоков вдруг задумает тебя задинамить на 10 сек? Владелец ты, или нет ... будешь висеть 10 сек на ожидании. |