Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.55/11: Рейтинг темы: голосов - 11, средняя оценка - 4.55
2 / 2 / 0
Регистрация: 03.06.2009
Сообщений: 102
1

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

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

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

На первое время решил добавить в функции вот такую конструкцию:
C++
1
2
3
4
5
6
7
8
int some_function{
  static UINT32 entryCounter = 0;
  while(entryCounter!= 0) Sleep(1);{
    entryCounter++;
    //тело функции
     entryCounter--;
  }
}
проблемы ушли, но интересно насколько корректный вариант получился и есть ли другие варианты решения данной проблемы?
Спасибо.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
24.07.2013, 14:23
Ответы с готовыми решениями:

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

Реализация функции печати результатов предыдущей функции
Была написана программа с функцией, находящая результат выражения с аргументом, значения которого...

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

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

37
2 / 2 / 0
Регистрация: 03.06.2009
Сообщений: 102
25.07.2013, 13:52  [ТС] 21
Author24 — интернет-сервис помощи студентам
Вроде бы понял.
Спасибо большое за книжку, почитаю.

Добавлено через 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
73 / 73 / 18
Регистрация: 29.11.2011
Сообщений: 356
25.07.2013, 13:54 22
Я всегда так делаю
0
Ушел с форума
Эксперт С++
16473 / 7436 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
25.07.2013, 14:02 23
Цитата Сообщение от smithana Посмотреть сообщение
есть ли слабые места у этого способа?
Есть. Забудете однажды вызвать close и все повиснет.
0
73 / 73 / 18
Регистрация: 29.11.2011
Сообщений: 356
25.07.2013, 14:21 24
Чота я невнимателен был, я не так делаю. Уменя обычно в конструкторах EnterCriticalSection(...), а в деструкторах DeleteCriticalSection(...).

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

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

Добавлено через 4 минуты
Цитата Сообщение от CheshireCat Посмотреть сообщение
ТС быстро придет к мысли об использовании RAII.....
Кстати, приведи пример, как бы ты в данном случае использовал бы RAII? Не пытаюсь мериться, действительно интересно.
0
Эксперт С++
2924 / 1274 / 114
Регистрация: 27.05.2008
Сообщений: 3,465
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
73 / 73 / 18
Регистрация: 29.11.2011
Сообщений: 356
25.07.2013, 15:16 28
Цитата Сообщение от CheshireCat Посмотреть сообщение
locker(&g_cs);
У тебя после конструктора сразу деструктор вызовется. МБ нужно всё таки экземпляр где-то сохранить?
А за идею спасибо
0
2 / 2 / 0
Регистрация: 03.06.2009
Сообщений: 102
25.07.2013, 15:17  [ТС] 29
Цитата Сообщение от Убежденный Посмотреть сообщение
Есть. Забудете однажды вызвать close и все повиснет.
ну это будет проблема разработчика приложения. Я думаю ему всё-таки будет легче не забывать close вызывать, чем самому с threadSafe разбираться.

Цитата Сообщение от Praktolock Посмотреть сообщение
Чота я невнимателен был, я не так делаю. Уменя обычно в конструкторах EnterCriticalSection(...), а в деструкторах DeleteCriticalSection(...).
а где же InitializeCriticalSection?
0
73 / 73 / 18
Регистрация: 29.11.2011
Сообщений: 356
25.07.2013, 15:20 30
Цитата Сообщение от smithana Посмотреть сообщение
а где же InitializeCriticalSection?
Опечатка: в конструкторе InitializeCriticalSection
0
Эксперт С++
4985 / 3092 / 456
Регистрация: 10.11.2010
Сообщений: 11,169
Записей в блоге: 10
25.07.2013, 15:22 31
Цитата Сообщение от Praktolock Посмотреть сообщение
У тебя после конструктора сразу деструктор вызовется.
Не сразу, а при выходе из метода.
0
73 / 73 / 18
Регистрация: 29.11.2011
Сообщений: 356
25.07.2013, 15:24 32
Цитата Сообщение от castaway Посмотреть сообщение
Не сразу, а при выходе метода.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class A
{
public:
 int value;
 A(){printf("A::A()\n");};
~A(){printf("A::~A()\n");};
};
 
int main()
{
 A();
 printf("s tvoih slov destructor doljen bit vizvan posle etoy stroki\n");
 _getch();
 return 0;
}
вывод:
A::A()
A::~A()
s tvoih slov destructor doljen bit vizvan posle etoy stroki
0
2 / 2 / 0
Регистрация: 03.06.2009
Сообщений: 102
25.07.2013, 15:26  [ТС] 33
Цитата Сообщение от Praktolock Посмотреть сообщение
Опечатка: в конструкторе InitializeCriticalSection
на первое время так и сделаю.

в RAII чуть позже постараюсь вникнуть. По первым впечатлениям вещь очень нужная.

Спасибо!
0
73 / 73 / 18
Регистрация: 29.11.2011
Сообщений: 356
25.07.2013, 15:29 34
Цитата Сообщение от Убежденный Посмотреть сообщение
Забудете однажды вызвать close и все повиснет.
Цитата Сообщение от CheshireCat Посмотреть сообщение
locker(&g_cs);
Забыли один раз экземпляру имя дать и получился баг

Добавлено через 1 минуту
который
Цитата Сообщение от CheshireCat Посмотреть сообщение
"зависает" раз в месяц, только на оборудовании Заказчика, и еще нерегулярно - в зависимости от положения звезд
Добавлено через 35 секунд
Так может быть, всё таки не в идеологии дело, а втом что нужно учиться не забывать?
0
Эксперт С++
4985 / 3092 / 456
Регистрация: 10.11.2010
Сообщений: 11,169
Записей в блоге: 10
25.07.2013, 15:33 35
Praktolock,
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <cstdio>
 
class A
{
public:
    int value;
    A() { printf("A::A()\n"); }
    ~A() { printf("A::~A()\n"); }
};
 
int main()
{
    A   a;
    printf("s tvoih slov destructor doljen bit vizvan posle etoy stroki\n");
    return 0;
}
Вывод:
A::A()
s tvoih slov destructor doljen bit vizvan posle etoy stroki
A::~A()
Просто надо уметь правильно это использовать.
0
Эксперт С++
2924 / 1274 / 114
Регистрация: 27.05.2008
Сообщений: 3,465
25.07.2013, 15:33 36
Верно, забыл. Писал код прямо в редакторе форума. Виноват-с... :-(
0
Ушел с форума
Эксперт С++
16473 / 7436 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
25.07.2013, 15:33 37
Цитата Сообщение от Praktolock Посмотреть сообщение
Не аргумент - забыть можно всё что угодно, и даже если не повиснет, это будет баг, который надо будет искать в любом случае. Тем более что баг, который приводит к зависанию проще отловить.
Цитата Сообщение от smithana Посмотреть сообщение
ну это будет проблема разработчика приложения. Я думаю ему всё-таки будет легче не забывать close вызывать, чем самому с threadSafe разбираться.
Ошибаетесь, господа.
Как только в коде появляются ветвления, такие ошибки начинают возникать на пустом месте.
И во время внесения изменений (рефакторинг) с таким подходом будет очень легко напортачить,
если использовать "голые" программные интерфейсы, не прикрытые RAII.
Интерфейсы open-do-close хороши только в вырожденных случаях, сведенных к функциям в
двадцать строк, где все на ладони и нет инвариантов.

Кроме того, если во время использования "голого" интерфейса кто-нибудь кинет исключение,
очистка ресурсов не будет выполнена и произойдет утечка. Так что без RAII никуда.

Цитата Сообщение от Praktolock Посмотреть сообщение
Так может быть, всё таки не в идеологии дело, а втом что нужно учиться не забывать?
Можно держать в уме все нужные контакты и планы встреч.
А можно пользоваться ежедневником и напоминалками, освобождая мозг для других задач.
Я предпочитаю второе.
0
73 / 73 / 18
Регистрация: 29.11.2011
Сообщений: 356
25.07.2013, 15:41 38
Цитата Сообщение от Убежденный Посмотреть сообщение
если во время использования "голого" интерфейса кто-нибудь кинет исключение,
очистка ресурсов не будет выполнена и произойдет утечка
Если "кто-то" кинет исключение не предусмотренное мной, это краш программы, и ресурсы ей больше не понадобятся.
Впрочем я не пытаюсь сказать, что RAII это плохо. И в принципе на 95% согласен.
0
25.07.2013, 15:41
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
25.07.2013, 15:41
Помогаю со студенческими работами здесь

Реализация функции srcat.
Я написал (реализовал) функцию strcat. Вот ... #include &quot;stdafx.h&quot; #include &lt;iostream&gt;...

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

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

Реализация friend функции
Есть код. Нужно реализовать вывод ответа через friend. Подскажите пожалуйста как это сделать?...


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

Или воспользуйтесь поиском по форуму:
38
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru