2 / 2 / 0
Регистрация: 03.06.2009
Сообщений: 102

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

24.07.2013, 14:23. Показов 3030. Ответов 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
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
24.07.2013, 14:23
Ответы с готовыми решениями:

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

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

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

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

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

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

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

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

Цитата Сообщение от Praktolock Посмотреть сообщение
Чота я невнимателен был, я не так делаю. Уменя обычно в конструкторах EnterCriticalSection(...), а в деструкторах DeleteCriticalSection(...).
а где же InitializeCriticalSection?
0
 Аватар для Praktolock
73 / 73 / 18
Регистрация: 29.11.2011
Сообщений: 356
25.07.2013, 15:20
Цитата Сообщение от smithana Посмотреть сообщение
а где же InitializeCriticalSection?
Опечатка: в конструкторе InitializeCriticalSection
0
Эксперт С++
4986 / 3093 / 456
Регистрация: 10.11.2010
Сообщений: 11,170
Записей в блоге: 10
25.07.2013, 15:22
Цитата Сообщение от Praktolock Посмотреть сообщение
У тебя после конструктора сразу деструктор вызовется.
Не сразу, а при выходе из метода.
0
 Аватар для Praktolock
73 / 73 / 18
Регистрация: 29.11.2011
Сообщений: 356
25.07.2013, 15:24
Цитата Сообщение от 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  [ТС]
Цитата Сообщение от Praktolock Посмотреть сообщение
Опечатка: в конструкторе InitializeCriticalSection
на первое время так и сделаю.

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

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

Добавлено через 1 минуту
который
Цитата Сообщение от CheshireCat Посмотреть сообщение
"зависает" раз в месяц, только на оборудовании Заказчика, и еще нерегулярно - в зависимости от положения звезд
Добавлено через 35 секунд
Так может быть, всё таки не в идеологии дело, а втом что нужно учиться не забывать?
0
Эксперт С++
4986 / 3093 / 456
Регистрация: 10.11.2010
Сообщений: 11,170
Записей в блоге: 10
25.07.2013, 15:33
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
Верно, забыл. Писал код прямо в редакторе форума. Виноват-с... :-(
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
25.07.2013, 15:33
Цитата Сообщение от Praktolock Посмотреть сообщение
Не аргумент - забыть можно всё что угодно, и даже если не повиснет, это будет баг, который надо будет искать в любом случае. Тем более что баг, который приводит к зависанию проще отловить.
Цитата Сообщение от smithana Посмотреть сообщение
ну это будет проблема разработчика приложения. Я думаю ему всё-таки будет легче не забывать close вызывать, чем самому с threadSafe разбираться.
Ошибаетесь, господа.
Как только в коде появляются ветвления, такие ошибки начинают возникать на пустом месте.
И во время внесения изменений (рефакторинг) с таким подходом будет очень легко напортачить,
если использовать "голые" программные интерфейсы, не прикрытые RAII.
Интерфейсы open-do-close хороши только в вырожденных случаях, сведенных к функциям в
двадцать строк, где все на ладони и нет инвариантов.

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

Цитата Сообщение от Praktolock Посмотреть сообщение
Так может быть, всё таки не в идеологии дело, а втом что нужно учиться не забывать?
Можно держать в уме все нужные контакты и планы встреч.
А можно пользоваться ежедневником и напоминалками, освобождая мозг для других задач.
Я предпочитаю второе.
0
 Аватар для Praktolock
73 / 73 / 18
Регистрация: 29.11.2011
Сообщений: 356
25.07.2013, 15:41
Цитата Сообщение от Убежденный Посмотреть сообщение
если во время использования "голого" интерфейса кто-нибудь кинет исключение,
очистка ресурсов не будет выполнена и произойдет утечка
Если "кто-то" кинет исключение не предусмотренное мной, это краш программы, и ресурсы ей больше не понадобятся.
Впрочем я не пытаюсь сказать, что RAII это плохо. И в принципе на 95% согласен.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
25.07.2013, 15:41

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

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
38
Ответ Создать тему
Опции темы

Новые блоги и статьи
Кредитный калькулятор
Maks 05.08.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Напишите приложение-калькулятор, которое помогает рассчитывать параметры кредита для аннуитетного и дифференцированного видов. . .
У нас сейчас поговорку "Опять 25" нужно переделать на "Опять +35".
kumehtar 04.08.2026
С ностальгией вспоминаю времена моего детства, когда у нас и правда +25 - была максимальная температура летом. Раньше +25 °C реально казались вершиной жары, когда можно было весь день пропадать на. . .
Как ИИ начал спорить и врать (возможно почуяв опасность для себя от индустрии - уход от электроники).
Hrethgir 04.08.2026
Недельный диалог, на фоне событий с НПЗ. Да, из спирта можно получать бензин, и это не сложно. Но потом в схеме я решил избавиться от насоса, при этом полностью сделав контроль подачи спирта в. . .
Термопринтер QR701
Argus19 03.08.2026
Термопринтер QR701 Купил два термопринтера QR701. На сэлф-тесте написано: Language: PC936 (GB18030). Что означает, что принтеры могут печатать только латиницу и китайские иероглифы. Так же. . .
Создание формы заимствованного документа
Maks 03.08.2026
Задача: Необходимо создать собственную форму заимствованного документа. На форме должен быть реквизит "Покупатель", а также табличная часть со следующими реквизитами: - Расчетный счет покупателя. . .
Задача предоставления скидок покупателям
Maks 03.08.2026
Задача: В документе "Продажи" необходимо реализовать функционал предоставления скидок покупателям. Скидка должна автоматически рассчитываться и подставляться в соответствующее поле при выборе. . .
Почему SEO не начинается с ключевых слов: что проверить до написания текстов
Neotwalker 01.08.2026
Когда владельцу сайта предлагают заняться SEO, первым шагом часто становится сбор запросов и написание текстов. Логика кажется понятной: 1. Находим ключевые слова. 2. Добавляем их на. . .
Знание — сила: Доктрина интенциональности знаний, углубление в формулу
Hrethgir 01.08.2026
https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11957&stc=1&d=1785567302 Знаменитый афоризм Фрэнсиса Бэкона «Знание — сила» (Scientia potentia est) в массовой культуре принято понимать. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru