На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
Страницы: (4) 1 2 [3] 4  все  ( Перейти к последнему сообщению )  
> Разгрузка CPU в потоке
    Цитата JoeUser @
    Если слип-задержку не раскоментить - как жрала прога 17% CPU, так и жрет. Это сразу было видно по твоему коду. Но я проверил на всяк случай:

    Потому что у тебя в цикле нет мониторинга чего либо, у тебя там выполняются конкретные действия, а не "мониторит состояние фискального аппарата". Вот ежели бы тебе нужно было мониторить папку на наличие в ней например какого то файла(появился - что то сделать), а до этого момента просто тупо цикл с проверкой - вот тогда это был бы мониторинг.


    Цитата JoeUser @
    Вот тут:
    CollapsedWrap disabledLine numbers off

    if (std::filesystem::exists(FileName))

    :facepalm: И как это условие связано с твоими флагами? :unsure:
      Цитата ЫукпШ @
      Ты не можешь подписаться в системе на такое событие - "наличие такого-то файла".

      В винде точно есть, но не помню и искать лень. Для FreeBSD вроде запилили libinotify. Про OSX не в курсе.

      Добавлено
      Цитата Wound @
      И как это условие связано с твоими флагами?

      Киля, спасибо за беседу! ;)
        Цитата JoeUser @
        Вот тут:
        CollapsedWrap disabledLine numbers off

        if (std::filesystem::exists(FileName))

        Если тебе нужно конкретно файл мониторить, то в принципе тебе выше написали решение:
        ExpandedWrap disabled
          #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 Пишешь одно, имея ввиду другое, потом еще фыркаешь. Я это запомню. Давай досвидания.
        Сообщение отредактировано: Qraizer -
          Цитата JoeUser @
          А вот теперь мне в своей проге понадобилось сделать что-то подобное.

          У мну жсм-шлюз читает/пишет смс-ки в/на ком-порт, достаточно одной таблэтки обычного слипа. нехер мудрствовать, бритва оккама в помощь.
            Цитата JoeUser @
            Перепишите мне с мьютексами, семафорами, или condition_variable чтобы стало лучше/правильнее. И что именно станет правильнее и лучше?
            Они тут по факту не нужны. Но если очень хочется, то можно. Очень хочется – это если хочешь один раз написать и не париться. На WinAPI множественные события ждутся элементарным WaitForMultipleObjects, которая тебе сразу и вернёт тот объект, который отнотифил. Очень удобно. Я бы хотел подобного в std, но коли его нет, можно написать самому: собираешь контейнер предикатов и ожидаешь по нужной комбинации условий, пока не сработают; выходишь с возвратом кортежа результатов предикатов, вызывающий пусть сам анализирует.
            Конкретно в твоём примере на cv имеет смысл завести лишь BreakEvent. Маловато, проще явно опрашивать.
              Цитата Qraizer @
              Они тут по факту не нужны. Но если очень хочется, то можно.

              В том то и дело, что Gonarh тут правильно упомянул Бритву Оккамы - если профита в данном случае нет, значит нафик и не нужно.

              Цитата Qraizer @
              На WinAPI множественные события ждутся элементарным WaitForMultipleObjects, которая тебе сразу и вернёт тот объект, который отнотифил. Очень удобно. Я бы хотел подобного в std

              Да я в курсе. И в *nix подобного очень не хватает, всякие там libevent + inotify + fsnotify запиливают, чтобы можно было реально засыпать на INFINITY время, но мочь всеж проснуться, а не дергать отдельные флаги или мьютексы.

              Цитата Qraizer @
              Конкретно в твоём примере на cv имеет смысл завести лишь BreakEvent. Маловато, проще явно опрашивать.

              Да нет - не "имеет смысл", а "можно сделать". Но лучше не делать, ибо сам ответил - "проще опрашивать".
                Цитата Qraizer @
                Я бы хотел подобного в std

                Этого и не будет никогда. По крайней мере если коренным образом не определят, что для обеспечения многозадачности С++ - операционная система должна обеспечивать событийную модель взаимодействия. ИМХО, нереально такое ждать.

                Смысл же WaitForSingleObject/WaitForMultipleObjects в чем? Ядро ОС приостанавливает поток до наступления "одного/одного из" событий (ну или если указано не бесконечное время ожидания) и не отдает ему управление (не ставит в очередь на получение квантов времени). Что мы имеем с std::this_thread::sleep_for? Ядро ОС усыпляет безусловно поток (не ставит в очередь на получение квантов времени) на единицу времени. А что имеем с std::this_thread::yield? Поток вычисления ядром ОС перебрасывается в конец очереди ожидания за получением своего кванта вычислений.

                И именно ядро усыпляет и пробуждает потоки. И С++ тут никак на этот механизм не может повлиять.

                Плюс ко всему в последних двух случаях (моей проги) периодически дергается проверка атомарного флага или мьютекса. И если поток не уcыплять - вот тут и ненужные вычисления , ну и бессмысленная загрузка CPU.
                  Смысл yield-а в том, чтобы, имея постоянную полезную работу, время от времени проталкивать фоновые процессы, если они есть. Если у тебя нет полезной работы, а пуллинг – это не полезная работа, это её ожидание, – yield не подходит идеологически.
                  Цитата JoeUser @
                  Этого и не будет никогда.
                  Я бы не был так категоричен. Его можно создать на имеющихся примитивах, притом что архитектурно его спроектировать не так-то просто, поэтому и нет пока, ибо комитет просто не хочет садиться в лужу очередной раз, как это уже случалось из-за непродуманной архитектуры библиотечной фичи. Реализовать полный аналог WaitForMultipleObjects() сложно, и ещё сложнее сделать этот механизм удобным и универсальным. Но конкретно ты конкретно в твоём приложении легко это сделаешь в частном порядке, не затратив существенных усилий.

                  Добавлено
                  Например. Если ожидать "любого из" объектов, то их надо опрашивать одновременно и тут же, как только, захватывать освободившийся. И всё это атомарно. Последнее условие непросто соблюсти, нельзя их опрашивать тупо по очереди, и захватывать первый попавшийся, будет race condition из-за того, что другой поток может быть позади тебя на пару объектов, и у него другой их набор, да ещё и на другом условии их комбинирования. Если нужно ждать "всех сразу", то последовательно тоже нельзя опрашивать и захватывать, будет dead lock по тем же причинам. Обеспечить атомарность можно, только имея контроль над сущностями, а не их представлениями, что вне ядра подсистемы синхронизации, типа как в винды, невозможно, т.к. изначально объекты синхронизации друг с другом никакими условиями не связаны и разными нитками запросто могут использоваться в разных комбинациях и даже поодиночке.
                  Сообщение отредактировано: Qraizer -
                    Цитата JoeUser @
                    Так вот первую функцию я не могу использовать по одной простой причине - пока она бесконечно висит я не могу завершить поток нормальным способом если вдруг мне это надо. Поэтому я использую вторую функцию с указанием тайм аута. Нет данных - пошла очередная итерация цикла. А вот в ней я уже могу анализировать BreakFlag. Если увижу что взведен - выхожу из цикла и завершаю поток.

                    Раз у тебя нет в арсенале неблокирующих функций, то никакие cv тебе не помогут. Читай с небольшим таймаутом и в каждой итерации проверяй флаг выхода, лучше особо ничего не сделаешь. Из очевидных минусов: необходимость доп. потока и завершение будет с задержкой (обычно это не критично).
                    Цитата JoeUser @
                    Я должен осуществлять другую операцию в потоке - вместо interception_wait_with_timeout ... что нибудь типа std::filesystem::exists("helloworld.txt"). И если файл найден - удалять. Делать пока поток не будет прерван. Если sleep в цикл не поставлю - "комп через час-два закипит"?

                    Простое решение - проверять со sleep'ом в цикле. Более сложное - использовать события ОС об изменения файла/каталога в асинхронном варианте. В Виндах это, например, ReadDirectoryChangesW.
                      Цитата Qraizer @
                      что вне ядра подсистемы синхронизации, типа как в винды, невозможно

                      Ключевые слова: "вне ядра невозможно". Можно написать кучу велосипедов, но пока нет доступа к ядерному планировщику потоков - это будет, имхо, только имитация. И да, в Линухах, *BSD-системах ядро открытое, там в принципе попытаться можно. Как? Я не в теме. Но думаю одним лишь загружаемым модулем не обойтись, как догадка.

                      shm, ты все правильно написал. Я так и реализовал, и других альтернатив не вижу. Хотя в моем случае - ожидание завершения потока, в принципе, можно зацепить на мьютекс. Но это ну совсем не критично в моем варианте. У меня это скорее дань к подходу к работе с внешними процессами, т.к. у меня выход из цикла - это по сути пару машиннх команд до завершения фонового потока.

                      Цитата shm @
                      Более сложное - использовать события ОС об изменения файла/каталога в асинхронном варианте.

                      Да, я бегло читал про возможности часто-используемых ОС-ей. В венде и линухах можно, во фряхе ... еще мутят (инфа от 2014 года), может уже и намутили.
                        Цитата Qraizer @
                        Я бы не был так категоричен.

                        То, что ты предлагаешь, в некоторых ЯП есть - это зеленые потоки. Но реализовать без языковой VM - это, по-сути, писать часть своей VM. Если бы комитет за это взялся - я бы просто офигел. Надеюсь С++ не скатится в недо си-шарпо-джавы.
                          Цитата JoeUser @
                          .. И в *nix подобного очень не хватает, всякие там libevent + inotify + fsnotify запиливают,

                          Имеется select, poll,epoll.
                          Выбирай по вкусу.
                            Цитата ЫукпШ @
                            Имеется 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.
                              Цитата JoeUser @
                              но пока нет доступа к ядерному планировщику потоков - это будет, имхо, только имитация

                              Дело не сколько в доступе к планировщику, а в обработке аппаратных прерываний.

                              Добавлено
                              Цитата JoeUser @
                              Хотя в моем случае - ожидание завершения потока, в принципе, можно зацепить на мьютекс.

                              И что тебе это даст?
                              Сообщение отредактировано: shm -
                                Цитата shm @
                                И что тебе это даст?

                                Временное примирение с Килей! :lol:

                                Добавлено
                                Цитата shm @
                                Дело не сколько в доступе к планировщику, а в обработке аппаратных прерываний.

                                А я не согласен!
                                Ну "захватил ты ресурс" (начал обрабатывать прерываание) , а если системный планировщик потоков вдруг задумает тебя задинамить на 10 сек? Владелец ты, или нет ... будешь висеть 10 сек на ожидании.
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (4) 1 2 [3] 4  все


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0514 ]   [ 17 queries used ]   [ Generated: 29.03.24, 08:31 GMT ]