Форум программистов, компьютерный форум CyberForum.ru

Уведомления между потоками - C++

Восстановить пароль Регистрация
 
 
eagl69
4 / 9 / 1
Регистрация: 12.10.2011
Сообщений: 440
29.07.2015, 11:35     Уведомления между потоками #1
Здравствуйте!
Набросал код для экспериментов:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include "stdafx.h"
 
int блок_1(HWND *hWnd, MyStruct* strukt_1);
int сервис_1(HWND *hWnd, MyStruct* strukt_1);
 
void блок(HWND *hWnd, MyStruct* strukt_1)//запускаем основной поток
{
    int q = 0;
    do
    {
        std::thread potok_блок_1(блок_1, hWnd, strukt_1);
        potok_блок_1.detach();//отсоединение потока
        std::thread potok_сервис_1(сервис_1, hWnd, strukt_1);
        potok_сервис_1.detach();//отсоединение потока
        ++q;
    }
    while ( q != 9 );
}
 
int блок_1(HWND *hWnd, MyStruct* strukt_1)//поток подключения
{   
    do
    {
        Sleep(1000);//10 сек
        (*strukt_1).a = 0;
    }
    while ( true );
    return 0;
}
 
int сервис_1(HWND *hWnd, MyStruct* strukt_1)//поток подключения
{
    do
    {
        Sleep(10);
        
    }
    while ( (*strukt_1).a != 0 );
    return 0;
}
Смысл такой, запускаю 20 фоновых потоков. теперь после каких-то вычислений какой либо из потоков блок_1 изменяет состояние в структуре. А в потоках сервис_1 жду этого изменения в цикле время от времени проверяя... Так вот вопрос в том, как избавится от этих циклов? чтобы не грузить систему. А остановить поток пока не будет сделано изменений в потоке блок_1.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
29.07.2015, 11:35     Уведомления между потоками
Посмотрите здесь:

C++ Работа с потоками
Работа с потоками. C++
C++ Работа с потоками
C++ проблема с потоками
C++ Работа с потоками
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Ilot
Модератор
Эксперт С++
1765 / 1140 / 221
Регистрация: 16.05.2013
Сообщений: 3,017
Записей в блоге: 5
Завершенные тесты: 1
29.07.2015, 12:03     Уведомления между потоками #2
Используйте условные переменные. На вашем псевдокоде и по одному потоку для блока и сервиса код будет выглядеть вот так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
std::mutex m;
std::condition_variable cv;
int блок_1(HWND *hWnd, MyStruct* strukt_1)//поток подключения
{   
    prepare_data();//<-готовим данные
    cv.notify_one();
    return 0;
}
 
int сервис_1(HWND *hWnd, MyStruct* strukt_1)//поток подключения
{
    std::unique_lock<std::mutex> lk(m);
    cv.wait(lk, []() { return (*strukt_1).a == 0;});
    do_proccesing(); //<-выполняем, что нужно
    return 0;
}
Что бы более конкретно ответить на вопрос о синхронизации нужно знать больше о том как должны взаимодействовать между собой потоки.
Praktolock
 Аватар для Praktolock
58 / 58 / 0
Регистрация: 29.11.2011
Сообщений: 272
29.07.2015, 12:06     Уведомления между потоками #3
Ну это не по языку вопрос а по платформе, для которой этот код предназначен.
Ilot
Модератор
Эксперт С++
1765 / 1140 / 221
Регистрация: 16.05.2013
Сообщений: 3,017
Записей в блоге: 5
Завершенные тесты: 1
29.07.2015, 12:10     Уведомления между потоками #4
Цитата Сообщение от Praktolock Посмотреть сообщение
Ну это не по языку вопрос а по платформе, для которой этот код предназначен.
Библиотека С++ (в разделе которого мы находимся ) кроссплатформена.
eagl69
4 / 9 / 1
Регистрация: 12.10.2011
Сообщений: 440
29.07.2015, 12:23  [ТС]     Уведомления между потоками #5
C++
1
cv.wait(lk, []() { return (*strukt_1).a == 0;});
здесь выдает 2 ошибки:

Ошибка C3493 "strukt_1" нельзя передать неявно, поскольку не задан режим передачи по умолчанию Win32Project1 c:\users\admin1\documents\visual studio 2015\projects\win32project1\win32project1\блок_.cpp 37

Ошибка IntelliSense: на локальную переменную со вложенной функцией нельзя ссылаться внутри тела лямбды, если она не находится в списке записей Win32Project1 c:\Users\Admin1\Documents\Visual Studio 2015\Projects\Win32Project1\Win32Project1\Блок_.cpp 37
Praktolock
 Аватар для Praktolock
58 / 58 / 0
Регистрация: 29.11.2011
Сообщений: 272
29.07.2015, 12:23     Уведомления между потоками #6
Цитата Сообщение от Ilot Посмотреть сообщение
Библиотека С++ (в разделе которого мы находимся ) кроссплатформена.
Цитата Сообщение от eagl69 Посмотреть сообщение
чтобы не грузить систему
библиотека да, а система нет
Ilot
Модератор
Эксперт С++
1765 / 1140 / 221
Регистрация: 16.05.2013
Сообщений: 3,017
Записей в блоге: 5
Завершенные тесты: 1
29.07.2015, 12:29     Уведомления между потоками #7
eagl69, в блямба-функции нужно хапать локальные переменные переменные:
C++
1
cv.wait(lk, [=]() { return (*strukt_1).a == 0;});
Либо делать переменные глобальными. Кажется так...
eagl69
4 / 9 / 1
Регистрация: 12.10.2011
Сообщений: 440
29.07.2015, 12:29  [ТС]     Уведомления между потоками #8
Цитата Сообщение от Praktolock Посмотреть сообщение
библиотека да, а система нет
Вы хотите сказать что циклом вполне можно обойтись? Но если убрать Sleep() то все виснет....
Praktolock
 Аватар для Praktolock
58 / 58 / 0
Регистрация: 29.11.2011
Сообщений: 272
29.07.2015, 12:44     Уведомления между потоками #9
Цитата Сообщение от eagl69 Посмотреть сообщение
Вы хотите сказать что циклом вполне можно обойтись?
Конечно можно.
Цитата Сообщение от eagl69 Посмотреть сообщение
Но если убрать Sleep() то все виснет....
Как виснет? Наглухо или подтормаживает просто?
eagl69
4 / 9 / 1
Регистрация: 12.10.2011
Сообщений: 440
29.07.2015, 12:53  [ТС]     Уведомления между потоками #10
Цитата Сообщение от Praktolock Посмотреть сообщение
Как виснет? Наглухо или подтормаживает просто?
загрузка цп под 100% т.к. в цикл выполняется быстро. А зачем тогда придуманы эти condition_variable если и проверкой в цикле переменной вполне можно обойтись? Я так думал что пока поток не спит то он жрет ресурсы... поэтому его лучше приостановить.

Добавлено через 1 минуту
А можно послать уведомление одному из 10 потоков? а не всем сразу? например по его ID?

Добавлено через 13 секунд
А можно послать уведомление одному из 10 потоков? а не всем сразу? например по его ID?
Praktolock
 Аватар для Praktolock
58 / 58 / 0
Регистрация: 29.11.2011
Сообщений: 272
29.07.2015, 13:01     Уведомления между потоками #11
Цитата Сообщение от eagl69 Посмотреть сообщение
загрузка цп под 100% т.к. в цикл выполняется быстро
Ну так не убирай Sleep)
Цитата Сообщение от eagl69 Посмотреть сообщение
А зачем тогда придуманы эти condition_variable если и проверкой в цикле переменной вполне можно обойтись?
С ними код компактнее и понятнее
Цитата Сообщение от eagl69 Посмотреть сообщение
А можно послать уведомление одному из 10 потоков? а не всем сразу? например по его ID?
Конечно можно. Ну самое что первое приходит в голову, вместо одной переменной сделать массив, в котором по одной такой переменной для каждого потока, и потоку например передавать указатель на егошнюю
Ilot
Модератор
Эксперт С++
1765 / 1140 / 221
Регистрация: 16.05.2013
Сообщений: 3,017
Записей в блоге: 5
Завершенные тесты: 1
29.07.2015, 13:02     Уведомления между потоками #12
Цитата Сообщение от eagl69 Посмотреть сообщение
А зачем тогда придуманы эти condition_variable если и проверкой в цикле переменной вполне можно обойтись?
Нельзя. Условные переменные это тот самый механизм, который позволяет ждать события не загружая систему.
Более того если пользоваться циклом переменная должна быть атомарна, либо необходимо заводить мъютекс для защиты флага.

Цитата Сообщение от eagl69 Посмотреть сообщение
А можно послать уведомление одному из 10 потоков? а не всем сразу? например по его ID?
Да. Функцией notify_one(). Разбудить все ожидающие потоки позволяет функция notify_all() условной переменной.
Что бы разбудить конкретный поток заведите для него отдельную условную переменную, ибо стандарт не дает никаких гарантий относительно того какой поток будет разбужен функцией notify_one().
eagl69
4 / 9 / 1
Регистрация: 12.10.2011
Сообщений: 440
29.07.2015, 13:09  [ТС]     Уведомления между потоками #13
У меня так и реализовано сейчас, но только проверка в цикле этих переменных. Вот я и подумал от них избавится.

Добавлено через 4 минуты
Я правильно понял что сделав массив перименных функцией notify_one() разбудится только тот поток где ожидается изменение именно той переменной? например так: cv.wait(lk, [=]() { return (*strukt_1)[1].a == 0;});

Добавлено через 55 секунд
а потоки где идет проверка:cv.wait(lk, [=]() { return (*strukt_1)[2].a == 0;}); не будут просыпаться?
Ilot
Модератор
Эксперт С++
1765 / 1140 / 221
Регистрация: 16.05.2013
Сообщений: 3,017
Записей в блоге: 5
Завершенные тесты: 1
29.07.2015, 13:13     Уведомления между потоками #14
eagl69, не правильно поняли. Нужно создавать массив условных переменных
C++
1
std::condition_variable cv[10];
И в каждом потоке ждать отдельную условную переменную.
C++
1
cv[index].wait(lk, [=]() { return /*условия могут отличаться для разных потоков*/;})
eagl69
4 / 9 / 1
Регистрация: 12.10.2011
Сообщений: 440
29.07.2015, 13:28  [ТС]     Уведомления между потоками #15
А можно сделать так: в структуре создать std::condition_variable cv; а массив сделать из структуры.
C++
1
2
3
4
5
6
7
struct a
{
int a=1;
std::condition_variable cv;
}
 
std::vector<a> aa(10);
Добавлено через 1 минуту
C++
1
aa[1].cv.wait(lk, [=]() { return /*условия могут отличаться для разных потоков*/;})
Добавлено через 1 минуту
Те хочу добиться чтобы каждой группе данных соответствовал свой condition_variable
Ilot
Модератор
Эксперт С++
1765 / 1140 / 221
Регистрация: 16.05.2013
Сообщений: 3,017
Записей в блоге: 5
Завершенные тесты: 1
29.07.2015, 13:34     Уведомления между потоками #16
Цитата Сообщение от eagl69 Посмотреть сообщение
Те хочу добиться чтобы каждой группе данных соответствовал свой condition_variable
Так будет правильнее и сия конструкция носит гордое название инкапсуляция.
Хотя вектор лучше не использовать.
eagl69
4 / 9 / 1
Регистрация: 12.10.2011
Сообщений: 440
29.07.2015, 13:43  [ТС]     Уведомления между потоками #17
А чем плох вектор?

Добавлено через 1 минуту
Дело в том что у меня в структуре данные разных типов....
Ilot
Модератор
Эксперт С++
1765 / 1140 / 221
Регистрация: 16.05.2013
Сообщений: 3,017
Записей в блоге: 5
Завершенные тесты: 1
29.07.2015, 13:54     Уведомления между потоками #18
Цитата Сообщение от eagl69 Посмотреть сообщение
А чем плох вектор?
Вектор требует наличие конструктора по умолчанию, конструктора копирования и оператора присвоения для хранимах объектов. Ни первого, ни второго, ни третьего у условных переменных нет. Вы элементарно не сможете поместить свои структуры в вектор с помощью push_back. Но если вы полагаете использовать emplace-функции то тоже можете нарваться на неприятности при перераспределении памяти вектора. Одним словом сплошные нихт зер гут.
eagl69
4 / 9 / 1
Регистрация: 12.10.2011
Сообщений: 440
29.07.2015, 14:02  [ТС]     Уведомления между потоками #19
А чем тогда лучше пользоваться?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
29.07.2015, 14:23     Уведомления между потоками
Еще ссылки по теме:

Отправка уведомления на e-mail C++
Работа с потоками C++
C++ передача данных между потоками

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Ilot
Модератор
Эксперт С++
1765 / 1140 / 221
Регистрация: 16.05.2013
Сообщений: 3,017
Записей в блоге: 5
Завершенные тесты: 1
29.07.2015, 14:23     Уведомления между потоками #20
Цитата Сообщение от eagl69 Посмотреть сообщение
А чем тогда лучше пользоваться?
Массивы или независимое объявление.
Yandex
Объявления
29.07.2015, 14:23     Уведомления между потоками
Ответ Создать тему
Опции темы

Текущее время: 04:42. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru