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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 9, средняя оценка - 4.67
smithana
2 / 2 / 0
Регистрация: 03.06.2009
Сообщений: 102
#1

реализация ThreadSafe функции - C++

24.07.2013, 14:23. Просмотров 1149. Ответов 37
Метки нет (Все метки)

Пишу статическую библиотеку функций, на основе которой разрабатывают приложения.
При создании многопоточных приложений на её основе начались проблемы. Думаю, что это связано с тем, что разные потоки мешаются друг другу, заходя в одну и туже функцию библиотеки.

На первое время решил добавить в функции вот такую конструкцию:
C++
1
2
3
4
5
6
7
8
int some_function{
  static UINT32 entryCounter = 0;
  while(entryCounter!= 0) Sleep(1);{
    entryCounter++;
    //тело функции
     entryCounter--;
  }
}
проблемы ушли, но интересно насколько корректный вариант получился и есть ли другие варианты решения данной проблемы?
Спасибо.
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
24.07.2013, 14:23
Здравствуйте! Я подобрал для вас темы с ответами на вопрос реализация ThreadSafe функции (C++):

Являются ли new / malloc threadsafe? - C++
И, если не являются, как организовать выделение памяти для многопоточной системы? Ставить мьютекс как-то слишком, особенно если выделяется...

Реализация функции c++ - C++
Программа: #include <iostream> using namespace std; struct Node { int data; Node* next; };

Реализация функции itoa - C++
помогите написать реализацию функции itoa MyItoa(int,char*,int) и пожалуйста с комменториями

Реализация функции strtok - C++
Добрый день. Мое задание звучит так: изучите поведение функции strtok из стандартной библиотеки. Реализуйте и...

Реализация функции srcat. - C++
Я написал (реализовал) функцию strcat. Вот ... #include "stdafx.h" #include <iostream> #include <iomanip> using namespace std;...

Реализация friend функции - C++
Есть код. Нужно реализовать вывод ответа через friend. Подскажите пожалуйста как это сделать? Ничего не получается... #include <iostream>...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
smithana
2 / 2 / 0
Регистрация: 03.06.2009
Сообщений: 102
24.07.2013, 16:10  [ТС] #16
Спасибо большое, попробую перевести всё на критическую секцию.

Правильно ли я понимаю:
У каждой функции должна быть своя критическая секция (чтобы разные потоки могли вызывать разные функции одновременно).
Пример функции:
C++
1
2
3
4
5
6
7
8
bool lib_function{
  static CRITICAL_SECTION cs; 
  EnterCriticalSection(&cs);
  //тут тело самой функции где перед каждым возможным return false;
  //я ставлю LeaveCriticalSection(&cs);
  LeaveCriticalSection(&cs);
  return true;
}
0
Praktolock
65 / 65 / 1
Регистрация: 29.11.2011
Сообщений: 300
24.07.2013, 16:12 #17
Цитата Сообщение от smithana Посмотреть сообщение
Правильно ли я понимаю:
У каждой функции должна быть своя критическая секция
Нет, неправильно. Критичиские секции лучше ставить только при чтении/записи данных к которым может обратиться ещо что-то, для гарантии что эти данные во время чтения/записи не будут изменены чем-то еще. Иначе будет некислое падение производительности, если втыкать их везде где вздумается.
0
smithana
2 / 2 / 0
Регистрация: 03.06.2009
Сообщений: 102
24.07.2013, 16:30  [ТС] #18
я опять не правильно выразился.
естественно не ко всем функциям библиотеки вообще, а только
к которым может обратиться ещо что-то
правильно ли я добавил вход и выход из критической секции?
0
CheshireCat
Эксперт С++
2892 / 1241 / 78
Регистрация: 27.05.2008
Сообщений: 3,370
24.07.2013, 16:38 #19
Да, вход и выход добавил правильно. Не забывай только про InitializeCriticalSection(&cs) и про возможные неприятности при исключениях. Удачи!
1
Praktolock
65 / 65 / 1
Регистрация: 29.11.2011
Сообщений: 300
24.07.2013, 16:42 #20
Я чувствую, что ты упускаешь самый важный посыл в моих постах. Внимательно прочитай следующее. Не в коде дело, а в данных с которыми этот код работает, то есть например такая функция
C++
1
2
3
4
5
6
int veryimportantfuntcion(int a, int b)
{
 int c=a+b;      //неважно какой тут код,
 a=c*a*b;       //как мы видим он никаких данных кроме переменных
 return(a++);   //обьявленных внутри себя не меняет и не читает
};
Тут не нужно никаких критических секций, её могут хоть 100500 потоков одновременно запустить и ничего страшного не случится. Но если функция обращается к каким-либо данным из-вне, например так:
C++
1
2
3
4
5
6
void sortmassiv(int*massiv, int kolichestvoelementov)
{
 EnterCriticalSection(&cs);
 //тут сортируем массив
 LeaveCriticalSection(&cs);
};
То тут критическая секция нужна, ибо пока мы сортируем его, наш поток может быть прерван, и например длинна массива уменьшится, в то время как наша функция об этом не узнает, да и порядок нарушится и массив отсортируется неправильно

Добавлено через 4 минуты
Хочу посоветовать книгу Джеффри Рихтера "Создание эффективных win32-приложений с учетом специфики 64-разрядной версии windows". Там об этом есть
1
smithana
2 / 2 / 0
Регистрация: 03.06.2009
Сообщений: 102
25.07.2013, 13:52  [ТС] #21
Вроде бы понял.
Спасибо большое за книжку, почитаю.

Добавлено через 20 часов 34 минуты
подумав, понял что инициализацию и удаление надо из функций выносить и решил сделать так:
1. Переменные критических секций поля класса.
2. Инициализация при открытии устройства.
3. Использование в функциях.
4. удаление в функции закрытии устройства.
В коде получается так:
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
class my_class{
public:
    CRITICAL_SECTION g_cs;
 
    void open();
    void function();
    void close();
};
 
void my_class::open(){
  //Открытие устройства
  InitializeCriticalSection(&g_cs);
}
 
void my_class::function(){
  EnterCriticalSection(&g_cs);
  int a = 5;
  LeaveCriticalSection(&g_cs);
}
 
void my_class::close(){
  DeleteCriticalSection(&g_cs);
  //Закрытие устройства
}
есть ли слабые места у этого способа?
Спасибо.
0
Praktolock
65 / 65 / 1
Регистрация: 29.11.2011
Сообщений: 300
25.07.2013, 13:54 #22
Я всегда так делаю
0
Убежденный
Системный программист
Эксперт С++
15552 / 7060 / 1114
Регистрация: 02.05.2013
Сообщений: 11,468
Завершенные тесты: 1
25.07.2013, 14:02 #23
Цитата Сообщение от smithana Посмотреть сообщение
есть ли слабые места у этого способа?
Есть. Забудете однажды вызвать close и все повиснет.
0
Praktolock
65 / 65 / 1
Регистрация: 29.11.2011
Сообщений: 300
25.07.2013, 14:21 #24
Чота я невнимателен был, я не так делаю. Уменя обычно в конструкторах EnterCriticalSection(...), а в деструкторах DeleteCriticalSection(...).

Добавлено через 15 минут
Цитата Сообщение от Убежденный Посмотреть сообщение
Есть. Забудете однажды вызвать close и все повиснет.
Не аргумент - забыть можно всё что угодно, и даже если не повиснет, это будет баг, который надо будет искать в любом случае. Тем более что баг, который приводит к зависанию проще отловить.
0
CheshireCat
Эксперт С++
2892 / 1241 / 78
Регистрация: 27.05.2008
Сообщений: 3,370
25.07.2013, 14:25 #25
Цитата Сообщение от Praktolock Посмотреть сообщение
Тем более что баг, который приводит к зависанию проще отловить.
Ооо! А если оно "зависает" раз в месяц, только на оборудовании Заказчика, и еще нерегулярно - в зависимости от положения звезд?

Собссна, я уверен, что пару раз поискав такие трудноуловимые баги в ночь перед релизом, ТС быстро придет к мысли об использовании RAII.....
0
Praktolock
65 / 65 / 1
Регистрация: 29.11.2011
Сообщений: 300
25.07.2013, 14:35 #26
Цитата Сообщение от CheshireCat Посмотреть сообщение
если оно "зависает" раз в месяц, только на оборудовании Заказчика, и еще нерегулярно
Ок, тогда будет найти сложнее)
Всё-таки я считаю, что просто нужно взять привычку - не забывать. А то можно подумать, что забыть что-нибудь другое вполне приемлемо.

Добавлено через 4 минуты
Цитата Сообщение от CheshireCat Посмотреть сообщение
ТС быстро придет к мысли об использовании RAII.....
Кстати, приведи пример, как бы ты в данном случае использовал бы RAII? Не пытаюсь мериться, действительно интересно.
0
CheshireCat
Эксперт С++
2892 / 1241 / 78
Регистрация: 27.05.2008
Сообщений: 3,370
25.07.2013, 15:01 #27
Ну в данном то случае оно тривиально:
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
41
42
43
#include <windows.h>
 
class locker
{
    CRITICAL_SECTION* cs;
 
public:
    locker(CRITICAL_SECTION* obj): cs(obj)
    {
        ::EnterCriticalSection(cs);
    };
    ~locker()
    {
        ::LeaveCriticalSection(cs);
    }
};
 
class my_class
{
    CRITICAL_SECTION g_cs;
 
public:
    my_class()
    {
        ::InitializeCriticalSection(&g_cs);
    }
    ~my_class()
    {
        ::DeleteCriticalSection(&g_cs);
    }
    void some_function();
};
 
void my_class::some_function()
{
    locker(&g_cs);
    int a = 5;
}
 
int main()
{
    // ......
}
1
Praktolock
65 / 65 / 1
Регистрация: 29.11.2011
Сообщений: 300
25.07.2013, 15:16 #28
Цитата Сообщение от CheshireCat Посмотреть сообщение
locker(&g_cs);
У тебя после конструктора сразу деструктор вызовется. МБ нужно всё таки экземпляр где-то сохранить?
А за идею спасибо
0
smithana
2 / 2 / 0
Регистрация: 03.06.2009
Сообщений: 102
25.07.2013, 15:17  [ТС] #29
Цитата Сообщение от Убежденный Посмотреть сообщение
Есть. Забудете однажды вызвать close и все повиснет.
ну это будет проблема разработчика приложения. Я думаю ему всё-таки будет легче не забывать close вызывать, чем самому с threadSafe разбираться.

Цитата Сообщение от Praktolock Посмотреть сообщение
Чота я невнимателен был, я не так делаю. Уменя обычно в конструкторах EnterCriticalSection(...), а в деструкторах DeleteCriticalSection(...).
а где же InitializeCriticalSection?
0
Praktolock
65 / 65 / 1
Регистрация: 29.11.2011
Сообщений: 300
25.07.2013, 15:20 #30
Цитата Сообщение от smithana Посмотреть сообщение
а где же InitializeCriticalSection?
Опечатка: в конструкторе InitializeCriticalSection
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
25.07.2013, 15:20
Привет! Вот еще темы с ответами:

Реализация функции принтф - C++
Хелпуем товарищи, треба написать свою фукнцию принтф с форматной строкой(правда она слегка иная, чтобы не путать с уже существующей) ...

Реализация функции палиндрома - C++
Я написала функцию, функция нормально работает. Но так как я смотрела по примерам, мне не очень нравиться этот момент: for (t = str;...

Реализация функции erase() - C++
Как работает erase()? То есть, если у нас : prev, it, next - итераторы и выполняя erase(it), она очистит память, которую занимала it и...

Реализация дружественной (friend) функции - C++
Всем доброго времени суток. Хотел бы попросить помощи, ибо запутался. Задачи состоит в том, чтобы произвести сравнение объекта...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
25.07.2013, 15:20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru