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

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

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 9, средняя оценка - 4.67
smithana
2 / 2 / 0
Регистрация: 03.06.2009
Сообщений: 101
24.07.2013, 14:23     реализация ThreadSafe функции #1
Пишу статическую библиотеку функций, на основе которой разрабатывают приложения.
При создании многопоточных приложений на её основе начались проблемы. Думаю, что это связано с тем, что разные потоки мешаются друг другу, заходя в одну и туже функцию библиотеки.

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

Реализация функции srcat. C++
C++ Реализация функции принтф
C++ Собственная реализация функции конкатенации
C++ Реализация функции erase()
Реализация функции wait C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
smithana
2 / 2 / 0
Регистрация: 03.06.2009
Сообщений: 101
25.07.2013, 13:52  [ТС]     реализация ThreadSafe функции #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);
  //Закрытие устройства
}
есть ли слабые места у этого способа?
Спасибо.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Praktolock
 Аватар для Praktolock
58 / 58 / 0
Регистрация: 29.11.2011
Сообщений: 272
25.07.2013, 13:54     реализация ThreadSafe функции #22
Я всегда так делаю
Убежденный
Системный программист
 Аватар для Убежденный
14197 / 6212 / 985
Регистрация: 02.05.2013
Сообщений: 10,349
Завершенные тесты: 1
25.07.2013, 14:02     реализация ThreadSafe функции #23
Цитата Сообщение от smithana Посмотреть сообщение
есть ли слабые места у этого способа?
Есть. Забудете однажды вызвать close и все повиснет.
Praktolock
 Аватар для Praktolock
58 / 58 / 0
Регистрация: 29.11.2011
Сообщений: 272
25.07.2013, 14:21     реализация ThreadSafe функции #24
Чота я невнимателен был, я не так делаю. Уменя обычно в конструкторах EnterCriticalSection(...), а в деструкторах DeleteCriticalSection(...).

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

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

Добавлено через 4 минуты
Цитата Сообщение от CheshireCat Посмотреть сообщение
ТС быстро придет к мысли об использовании RAII.....
Кстати, приведи пример, как бы ты в данном случае использовал бы RAII? Не пытаюсь мериться, действительно интересно.
CheshireCat
Эксперт С++
2907 / 1235 / 78
Регистрация: 27.05.2008
Сообщений: 3,308
25.07.2013, 15:01     реализация ThreadSafe функции #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()
{
    // ......
}
Praktolock
 Аватар для Praktolock
58 / 58 / 0
Регистрация: 29.11.2011
Сообщений: 272
25.07.2013, 15:16     реализация ThreadSafe функции #28
Цитата Сообщение от CheshireCat Посмотреть сообщение
locker(&g_cs);
У тебя после конструктора сразу деструктор вызовется. МБ нужно всё таки экземпляр где-то сохранить?
А за идею спасибо
smithana
2 / 2 / 0
Регистрация: 03.06.2009
Сообщений: 101
25.07.2013, 15:17  [ТС]     реализация ThreadSafe функции #29
Цитата Сообщение от Убежденный Посмотреть сообщение
Есть. Забудете однажды вызвать close и все повиснет.
ну это будет проблема разработчика приложения. Я думаю ему всё-таки будет легче не забывать close вызывать, чем самому с threadSafe разбираться.

Цитата Сообщение от Praktolock Посмотреть сообщение
Чота я невнимателен был, я не так делаю. Уменя обычно в конструкторах EnterCriticalSection(...), а в деструкторах DeleteCriticalSection(...).
а где же InitializeCriticalSection?
Praktolock
 Аватар для Praktolock
58 / 58 / 0
Регистрация: 29.11.2011
Сообщений: 272
25.07.2013, 15:20     реализация ThreadSafe функции #30
Цитата Сообщение от smithana Посмотреть сообщение
а где же InitializeCriticalSection?
Опечатка: в конструкторе InitializeCriticalSection
castaway
Эксперт С++
4844 / 2983 / 367
Регистрация: 10.11.2010
Сообщений: 11,021
Записей в блоге: 10
Завершенные тесты: 1
25.07.2013, 15:22     реализация ThreadSafe функции #31
Цитата Сообщение от Praktolock Посмотреть сообщение
У тебя после конструктора сразу деструктор вызовется.
Не сразу, а при выходе из метода.
Praktolock
 Аватар для Praktolock
58 / 58 / 0
Регистрация: 29.11.2011
Сообщений: 272
25.07.2013, 15:24     реализация ThreadSafe функции #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
smithana
2 / 2 / 0
Регистрация: 03.06.2009
Сообщений: 101
25.07.2013, 15:26  [ТС]     реализация ThreadSafe функции #33
Цитата Сообщение от Praktolock Посмотреть сообщение
Опечатка: в конструкторе InitializeCriticalSection
на первое время так и сделаю.

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

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

Добавлено через 1 минуту
который
Цитата Сообщение от CheshireCat Посмотреть сообщение
"зависает" раз в месяц, только на оборудовании Заказчика, и еще нерегулярно - в зависимости от положения звезд
Добавлено через 35 секунд
Так может быть, всё таки не в идеологии дело, а втом что нужно учиться не забывать?
castaway
Эксперт С++
4844 / 2983 / 367
Регистрация: 10.11.2010
Сообщений: 11,021
Записей в блоге: 10
Завершенные тесты: 1
25.07.2013, 15:33     реализация ThreadSafe функции #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()
Просто надо уметь правильно это использовать.
CheshireCat
Эксперт С++
2907 / 1235 / 78
Регистрация: 27.05.2008
Сообщений: 3,308
25.07.2013, 15:33     реализация ThreadSafe функции #36
Верно, забыл. Писал код прямо в редакторе форума. Виноват-с... :-(
Убежденный
Системный программист
 Аватар для Убежденный
14197 / 6212 / 985
Регистрация: 02.05.2013
Сообщений: 10,349
Завершенные тесты: 1
25.07.2013, 15:33     реализация ThreadSafe функции #37
Цитата Сообщение от Praktolock Посмотреть сообщение
Не аргумент - забыть можно всё что угодно, и даже если не повиснет, это будет баг, который надо будет искать в любом случае. Тем более что баг, который приводит к зависанию проще отловить.
Цитата Сообщение от smithana Посмотреть сообщение
ну это будет проблема разработчика приложения. Я думаю ему всё-таки будет легче не забывать close вызывать, чем самому с threadSafe разбираться.
Ошибаетесь, господа.
Как только в коде появляются ветвления, такие ошибки начинают возникать на пустом месте.
И во время внесения изменений (рефакторинг) с таким подходом будет очень легко напортачить,
если использовать "голые" программные интерфейсы, не прикрытые RAII.
Интерфейсы open-do-close хороши только в вырожденных случаях, сведенных к функциям в
двадцать строк, где все на ладони и нет инвариантов.

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

Цитата Сообщение от Praktolock Посмотреть сообщение
Так может быть, всё таки не в идеологии дело, а втом что нужно учиться не забывать?
Можно держать в уме все нужные контакты и планы встреч.
А можно пользоваться ежедневником и напоминалками, освобождая мозг для других задач.
Я предпочитаю второе.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
25.07.2013, 15:41     реализация ThreadSafe функции
Еще ссылки по теме:

Являются ли new / malloc threadsafe? C++
C++ Реализация функции strtok
C++ Реализация функции itoa

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

Или воспользуйтесь поиском по форуму:
Praktolock
 Аватар для Praktolock
58 / 58 / 0
Регистрация: 29.11.2011
Сообщений: 272
25.07.2013, 15:41     реализация ThreadSafe функции #38
Цитата Сообщение от Убежденный Посмотреть сообщение
если во время использования "голого" интерфейса кто-нибудь кинет исключение,
очистка ресурсов не будет выполнена и произойдет утечка
Если "кто-то" кинет исключение не предусмотренное мной, это краш программы, и ресурсы ей больше не понадобятся.
Впрочем я не пытаюсь сказать, что RAII это плохо. И в принципе на 95% согласен.
Yandex
Объявления
25.07.2013, 15:41     реализация ThreadSafe функции
Ответ Создать тему
Опции темы

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