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

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

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

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

24.07.2013, 14:23. Просмотров 1191. Ответов 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>...

37
nexen
187 / 180 / 3
Регистрация: 27.01.2012
Сообщений: 1,335
24.07.2013, 14:26 #2
smithana, семафоры, мьютексы, евенты/таймеры (для извращенных личностей)
Или я не так вопрос понял?
0
smithana
2 / 2 / 0
Регистрация: 03.06.2009
Сообщений: 102
24.07.2013, 14:32  [ТС] #3
Спасибо, правильно!
Но смысла менять данную конструкцию на семафоры и мьютексы - не вижу.
Нашёл CRITICAL_SECTION, но не могу понять для моей ли это ситуации.
0
CheshireCat
Эксперт С++
2893 / 1242 / 78
Регистрация: 27.05.2008
Сообщений: 3,390
24.07.2013, 15:14 #4
Проблемы ушли, говоришь? Хех. Есть мнение, что тебе просто везет. Пока :-)
0
smithana
2 / 2 / 0
Регистрация: 03.06.2009
Сообщений: 102
24.07.2013, 15:21  [ТС] #5
Наверное не просто так я спрашиваю про корректность данного метода.
Если есть, что сказать по делу(сказать чем этот способ плох, предложить другой), я буду благодарен.
Если нет, то смысл злорадствовать?

з.ы.
Минус пока придумал только то, что если в функцию полезет одновременно больше двух потоков, будет хаос, и никакой очереди!
0
Praktolock
65 / 65 / 1
Регистрация: 29.11.2011
Сообщений: 300
24.07.2013, 15:30 #6
C++
1
2
while(entryCounter!= 0) Sleep(1);{
 entryCounter++;
Если поток прервётся между этих строк и начнёт работать другой, то твоя защита не сработает
0
nexen
187 / 180 / 3
Регистрация: 27.01.2012
Сообщений: 1,335
24.07.2013, 15:32 #7
smithana, критические секции тоже подойдут.
0
Praktolock
65 / 65 / 1
Регистрация: 29.11.2011
Сообщений: 300
24.07.2013, 15:34 #8
Почему не сделать так:
C++
1
2
3
4
5
6
int some_function()
{
 EnterCriticalSection(&criticalsection);
 dosomeaction();
 LeaveCriticalSection();
}
?

Добавлено через 1 минуту
Да и дело не в том, что два потока выполняют одну и ту же функцию, а в том что они читают/пишут одни и те же данные.
0
CheshireCat
Эксперт С++
2893 / 1242 / 78
Регистрация: 27.05.2008
Сообщений: 3,390
24.07.2013, 15:36 #9
На самом деле, тебе уже nexen посоветовал - используй стандартные средства синхронизации, но не самописный код. А в твоем коде очень легко и непринужденно может возникнуть ситуация, когда в тело функции входят одновременно несколько потоков, и начинается хаос.

Критическая секция (если говорить о Win) - это именно то, что тебе нужно. Только не забудь обернуть ее объектом, реализующим идиому RAII, в противном случае огребешь проблем, если "вдруг" из середины функции вылетит исключение.
C++
1
2
3
4
5
6
int some_function() {
    EnterCriticalSection(&criticalsection);
    dosomeaction(); // <=== вот если здесь вылетит исключение, функция останется 
                    // заблокированной навсегда - дедлок. 
    LeaveCriticalSection(&criticalsection);
}
Ну или можешь использовать стандартные средства синхронизации - к чему душа больше лежит....
1
Praktolock
65 / 65 / 1
Регистрация: 29.11.2011
Сообщений: 300
24.07.2013, 15:38 #10
Цитата Сообщение от CheshireCat Посмотреть сообщение
если "вдруг" из середины функции вылетит исключение.
В обработчике исключений можно предусмотреть вызов LeaveCriticalSection(&criticalsection). Твой совет относится больше к обработке исключений впринципе, чем к многопоточнобезопасности.
0
CheshireCat
Эксперт С++
2893 / 1242 / 78
Регистрация: 27.05.2008
Сообщений: 3,390
24.07.2013, 15:44 #11
Ээээ, нет! А ты уверен, что любое исключение будет перехвачено? Ась? Исключения могут быть разными, и более того - если функция dosomeaction() вызывает другие функции, а те - еще третьи, и так далее, можно ли всегда уверенно сказать, какое исключение может вылететь из глубины сибирских руд? Не буду уж напоминать про C++-исключения и SEH-исключения....
Имхо лучше применить универсальный подход, гарантирующий отсутствие проблем при любых исключениях.
0
Praktolock
65 / 65 / 1
Регистрация: 29.11.2011
Сообщений: 300
24.07.2013, 15:46 #12
Если неизвестно какие исключения могут вылететь из
Цитата Сообщение от CheshireCat Посмотреть сообщение
из глубины сибирских руд
, то каким образом нам после этих самых исключений может понадобиться "дедлок" функция dosomeaction(), раз мы не собираемся обрабатывать исключения "из глубины сибирских руд" и наш шедевр завершится сообщив о необработанном исключении?
0
smithana
2 / 2 / 0
Регистрация: 03.06.2009
Сообщений: 102
24.07.2013, 15:52  [ТС] #13
А есть ли смысл оборачивать в критическую секцию тело функции в самой функции в библиотеке?
Получается легче обернуть вызов функции библиотеки в самом многопоточном приложении.

идея была снять с разработчика приложения эту головную боль и реализовать threadSafe в самой библиотеке.
0
CheshireCat
Эксперт С++
2893 / 1242 / 78
Регистрация: 27.05.2008
Сообщений: 3,390
24.07.2013, 15:53 #14
Да лехко! Исключение может быть перехвачено и обработано в коде на несколько уровней выше по иерархии, чем функция dosomeaction(). Грубая схема:

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
int f1()
{
    try {
        // некие действия....
        f2();
    }
    catch(...)
    {
        // тут как бы очистка....
    }
}
 
 
int f2()
{
    // тут еще куча кода...
    f3();
}
 
int f3()
{
    static CRITICAL_SECTION cs;
    // код инициализации опускаем...
    EnterCriticalSection(&cs);
    dosomeaction();
    LeaveCriticalSection(&cs);
}
 
void dosomeaction()
{
    // куча кода.....
    f4();
}
 
void f4()
{
    // куча кода....
    throw SomeEvil("Babah!");
}
0
Praktolock
65 / 65 / 1
Регистрация: 29.11.2011
Сообщений: 300
24.07.2013, 16:04 #15
Цитата Сообщение от smithana Посмотреть сообщение
А есть ли смысл оборачивать в критическую секцию тело функции в самой функции в библиотеке?
Зависит от твоей библиотеки. Ты хочешь упростить использование библиотеки потребителю? Решать тебе

Добавлено через 1 минуту
Цитата Сообщение от CheshireCat Посмотреть сообщение
Исключение может быть перехвачено и обработано в коде на несколько уровней выше по иерархии
Это называется плохо продуманная архитектура.

Добавлено через 7 минут
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
44
45
46
47
int f1()
{
    try {
        // некие действия....
        f2();
    }
    catch(...)
    {
        // тут как бы очистка....
    }
}
 
 
int f2()
{
    // тут еще куча кода...
    f3();
}
 
int f3()
{
    static CRITICAL_SECTION cs;
    // код инициализации опускаем...
    EnterCriticalSection(&cs);
    try
    {
     dosomeaction();
    }
    catch(...)
    {
     LeaveCriticalSection(&cs);
     throw SomeEvil("Babah!");
    }
    LeaveCriticalSection(&cs);
}
 
void dosomeaction()
{
    // куча кода.....
    f4();
}
 
void f4()
{
    // куча кода....
    throw SomeEvil("Babah!");
}
Добавлено через 19 секунд
Раз уж очень приспичило можно и так
1
24.07.2013, 16:04
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
24.07.2013, 16:04
Привет! Вот еще темы с ответами:

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

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

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

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


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

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

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