Russian Qt Forum
Май 07, 2024, 12:59 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 2 [3] 4 5 ... 13   Вниз
  Печать  
Автор Тема: К вопросу об организации взаимодействия пула производителей и одного потребителя  (Прочитано 61145 раз)
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #30 : Сентябрь 08, 2019, 20:31 »

Стоп, так у вас два мьютекса вместо одного? Улыбающийся
Зачем, достаточно одного мьютекса.
Да, два  Улыбающийся Один для очереди, другой для condition_variable) А одним можно?  Улыбающийся

Аааа))) Дошло  Смеющийся
« Последнее редактирование: Сентябрь 08, 2019, 20:33 от m_ax » Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #31 : Сентябрь 08, 2019, 20:36 »

Спасибо, понял) Исправил)
« Последнее редактирование: Сентябрь 08, 2019, 20:48 от m_ax » Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #32 : Сентябрь 08, 2019, 20:56 »

Код
C++ (Qt)
   void worker()
   {
       while (!m_is_stop)
       {
           {
               std::unique_lock<std::mutex> lock(m_mutex);
               m_loop_cv.wait(lock, [&]()
               {
                   return !m_queue.empty() || m_is_stop;
               });
           }
 
           if (m_is_stop)
               return;
 
           std::function<void()> work_function([](){});
 
           {
               // std::lock_guard<std::mutex> lock(m_mutex);  <<< и так золочен
               // if (!m_queue.empty())  <<< тут точно не пусто - проверено в wait
               {
                   work_function = std::move(m_queue.front());
                   m_queue.pop();
               }
           }
          // Разлочиваем и запускаем работу
          lock.unlock();
 
          work_function();
       }
   }
 
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #33 : Сентябрь 08, 2019, 21:03 »

Нет..
Код
C++ (Qt)
while (!m_is_stop)
       {
           {
               std::unique_lock<std::mutex> lock(m_mutex);
               m_loop_cv.wait(lock, [&]()
               {
                   return !m_queue.empty() || m_is_stop;
               });
           }
           // <<< Здесь lock уже откинулся и освободил m_mutex
 
           if (m_is_stop)
               return;
 
           std::function<void()> work_function([](){});
 
           {
               // std::lock_guard<std::mutex> lock(m_mutex);  <<< и так золочен
               // if (!m_queue.empty())  <<< тут точно не пусто - проверено в wait
               {
                   work_function = std::move(m_queue.front());
                   m_queue.pop();
               }
           }
          // Разлочиваем и запускаем работу
          lock.unlock();
 
          work_function();
       }
   }
 
Можно тогда сделать так (чтоб дважды m_mutex не захватывать)
Код
C++ (Qt)
void worker()
   {
       while (!m_is_stop)
       {
           std::unique_lock<std::mutex> lock(m_mutex);
            m_loop_cv.wait(lock, [&]()
            {
                   return !m_queue.empty() || m_is_stop;
            });
 
 
           if (m_is_stop)
               return;
 
           std::function<void()> work_function(m_queue.front());
           m_queue.pop();
           lock.unlock();
 
          work_function();
       }
   }
 
« Последнее редактирование: Сентябрь 08, 2019, 21:11 от m_ax » Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #34 : Сентябрь 08, 2019, 21:12 »

// <<< Здесь lock уже откинулся и освободил m_mutex
Нет.
wait работает следующим образом (псевдокод):
Код
C++ (Qt)
wait( mutex m )
{
 m.unlock()
 yield()
 m.lock()
}
 

Т.е. он освобождает мьютекс и отдает управление планировщику, говоря производителям: я освободил мьютекс и жду когда вы накидаете мне в очередь работы. Производитель теперь может захватить мьютекс и положить работу в очередь. Затем он сигналит и освобождает мьютекс. Когда планировщик разбудит нить, управление вернется после yield, далее wait опять захватит мьютикс и завершится. Мьютекс снова захвачен, мы можем работать с очередью.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #35 : Сентябрь 08, 2019, 21:14 »

Можно тогда сделать так (чтоб дважды m_mutex не захватывать)
Так это тот же вариант, который получается с моими комментариями. Улыбающийся

UPDATE. Ааа, увидел что локер был в {}. Да последний вариант - нормальный.
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #36 : Сентябрь 08, 2019, 21:39 »

Цитировать
Да последний вариант - нормальный.
Исправил  Улыбающийся
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #37 : Сентябрь 09, 2019, 07:10 »

Код
C++ (Qt)
auto task_ptr = std::make_shared<std::packaged_task<decltype(work_function())()>>(std::forward<F>(work_function));
 
Не стоит так гнаться за модой Улыбающийся  Это лишь засирает мозги и отвлекает программиста от содержательной работы
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #38 : Сентябрь 09, 2019, 07:40 »

Код
C++ (Qt)
auto task_ptr = std::make_shared<std::packaged_task<decltype(work_function())()>>(std::forward<F>(work_function));
 
Не стоит так гнаться за модой Улыбающийся  Это лишь засирает мозги и отвлекает программиста от содержательной работы
Это не мода, а более общее решение, которое позволяет легко написать код как для случая, когда нужно дождаться завершения всех работ в пуле, так и для ожидания завершения только части работ. Ведь один и тот же пул может использоваться для разных типов работ, завершение каких-то работ нужно ждать в одном месте, завершение других  в другом.
« Последнее редактирование: Сентябрь 09, 2019, 07:42 от Old » Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #39 : Сентябрь 09, 2019, 12:18 »

Хотел поинтересоваться:
Код
C++ (Qt)
class thread_pool
{
...
private:
...
   std::list<std::shared_ptr<std::thread>> m_threads;
...
};
 

Почему shared_ptr использовали? Какой ход мыслей был, или на автомате? Мне  в исследовательских целях интересно Улыбающийся.
Записан

Пока сам не сделаешь...
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #40 : Сентябрь 09, 2019, 12:38 »

Хотел поинтересоваться:
Код
C++ (Qt)
class thread_pool
{
...
private:
...
   std::list<std::shared_ptr<std::thread>> m_threads;
...
};
 

Почему shared_ptr использовали? Какой ход мыслей был, или на автомате? Мне  в исследовательских целях интересно Улыбающийся.
Я по привычке, поскольку std::thread - некопируемый объект. А я все некопируемые объекты в контейнерах по указателю храню.. (Мало ли что  Улыбающийся)
А std::shared_ptr использовал чтоб не заморачиваться с их ручным удалением в деструкторе thread_poolа  Улыбающийся
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #41 : Сентябрь 09, 2019, 12:49 »

Я по привычке, поскольку std::thread - некопируемый объект. А я все некопируемые объекты в контейнерах по указателю храню.. (Мало ли что  Улыбающийся)
А std::shared_ptr использовал чтоб не заморачиваться с их ручным удалением в деструкторе thread_poolа  Улыбающийся

Ок, спасибо за ответ Улыбающийся.
Записан

Пока сам не сделаешь...
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #42 : Сентябрь 09, 2019, 13:01 »

Я по привычке, поскольку std::thread - некопируемый объект. А я все некопируемые объекты в контейнерах по указателю храню.. (Мало ли что  Улыбающийся)
Ну так он перемещаемый. Улыбающийся
Код
C++ (Qt)
vector<thread> m_threads;
 
и все. Улыбающийся

Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #43 : Сентябрь 09, 2019, 13:52 »

Я по привычке, поскольку std::thread - некопируемый объект. А я все некопируемые объекты в контейнерах по указателю храню.. (Мало ли что  Улыбающийся)
Ну так он перемещаемый. Улыбающийся
Код
C++ (Qt)
vector<thread> m_threads;
 
и все. Улыбающийся


Да, верно, перемещаемый)

PS Кстатии в boost::thread_group тоже используют список с указателями на thread  Улыбающийся
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #44 : Сентябрь 09, 2019, 13:59 »

PS Кстатии в boost::thread_group тоже используют список с указателями на thread  Улыбающийся
Это легаси. Улыбающийся
boost::thread появился в далеком 2001 году, когда о move-семантики даже не задумывались. Улыбающийся
Записан
Страниц: 1 2 [3] 4 5 ... 13   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.503 секунд. Запросов: 22.