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

Буферы и синхронизация потоков - C++

Восстановить пароль Регистрация
 
 
Praktolock
 Аватар для Praktolock
58 / 58 / 0
Регистрация: 29.11.2011
Сообщений: 272
15.06.2014, 14:36     Буферы и синхронизация потоков #1
Всем привет. Суть такова: есть(будет) некая софтина которая подгружает плагины(дмнамические библиотеки) создает поток с функцией из этого плагина и весь обмен происходит через буферы, которые нужно блокировать ну чтобы там писать/читать одновременно нельзя было. Для каждого плагина ровно 2 буфера, 1 для вывода из плагина, 1 для ввода. Не хочу использовать платформенно зависимые средства и буст тоже использовать не хочу. Оцените пожалуйста, бегло просмотрев, как оно норм работать будет? Ну именно блокирование.

buffer.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#pragma once
#include <vector>
 
struct STBUFFER
{
 std::vector<char>data;//а может и не вектор, еще я не решил
 int rbisy;
 int wbisy;
 STBUFFER();
 void gonnawrite();
 void gonnaread ();
 void finishedwrite();
 void finishedread ();
 
 int read(char*, int);
 int write(char*, int);
};
buffer.cpp
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
#include "buffer.h"
 
STBUFFER::STBUFFER()
{
 rbisy=0;
 wbisy=0;
};
 
void STBUFFER::gonnawrite()
{
 while(rbisy>0){/*какаянибудь пурга*/};
 wbisy++;
};
 
void STBUFFER::finishedwrite()
{
 wbisy--;
};
 
void STBUFFER::gonnaread()
{
 while(wbisy>0){/*какаянибудь пурга*/};
 rbisy++;
};
 
void STBUFFER::finishedread()
{
 rbisy--;
};
 
int STBUFFER::read(char*_buf, int _sz)
{
 gonnaread();
 //читаем, удоляем
 finishedread();
 return(0);
};
 
int STBUFFER::write(char*_buf, int _sz)
{
 gonnawrite();
 //пишем
 finishedwrite();
 return(_sz);
};
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
15.06.2014, 14:36     Буферы и синхронизация потоков
Посмотрите здесь:

C++ Синхронизация
C++ Синхронизация потоков средствами WinAPI.
Синхронизация доступа C++
C++ Синхронизация потоков, события, WinAPI
C++ Синхронизация потоков в c++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
0x10
2425 / 1597 / 232
Регистрация: 24.11.2012
Сообщений: 3,919
15.06.2014, 14:50     Буферы и синхронизация потоков #2
1. Еще раз задуматься об архитектуре. Возможно ли обращение из нескольких потоков к потокам? Обязательно ли взаимодействие через потоки? Пока мотивации не вижу.
2. Свои велосипеды на выброс. Если и заработает, то как минимум, работать будет неэффективно. Циклами с ожиданием - только проц греть.
Praktolock
 Аватар для Praktolock
58 / 58 / 0
Регистрация: 29.11.2011
Сообщений: 272
15.06.2014, 14:57  [ТС]     Буферы и синхронизация потоков #3
Цитата Сообщение от 0x10 Посмотреть сообщение
Циклами с ожиданием - только проц греть.
он не будет пустым, там оставлено место под какойнибудь sleep, например
C++
1
while(wbisy>0){/*какаянибудь пурга*/};
Цитата Сообщение от 0x10 Посмотреть сообщение
1. Еще раз задуматься об архитектуре. Возможно ли обращение из нескольких потоков к потокам? Обязательно ли взаимодействие через потоки? Пока мотивации не вижу.
Только 1 поток может писать только в 1 буфер, и только он может читать только из 1 другого буфера. В то время как 2-ой поток можеть писать только в 1 буфер, в тот с которого читает первый поток, и только он один можеть читать с буфера в который можеть писать один единственный поток (1-й). как-то так. На мой взгляд, архитектура идеальна.
0x10
2425 / 1597 / 232
Регистрация: 24.11.2012
Сообщений: 3,919
15.06.2014, 15:00     Буферы и синхронизация потоков #4
И да - работать не будет.

Добавлено через 1 минуту
Предположим, такая ситуация. Два потока хотят начать записывать данные.
Поток 1 - проверка условия wbusy - писать можно.
Поток 2 - проверка условия - писать можно
Поток 2 - увеличение значения wbusy
Поток 1 - увеличение значения wbusy

И вот у нас уже два потока ломятся на запись.
Praktolock
 Аватар для Praktolock
58 / 58 / 0
Регистрация: 29.11.2011
Сообщений: 272
15.06.2014, 15:27  [ТС]     Буферы и синхронизация потоков #5
Не не, не так, пишет только 1, читает только 1. Они не будут оба пытаться писать
Renji
1534 / 982 / 240
Регистрация: 05.06.2014
Сообщений: 2,958
15.06.2014, 15:28     Буферы и синхронизация потоков #6
Не хочу использовать платформенно зависимые средства и буст тоже использовать не хочу.
std::mutex. Стандартная библиотека, однако.
0x10
2425 / 1597 / 232
Регистрация: 24.11.2012
Сообщений: 3,919
15.06.2014, 15:32     Буферы и синхронизация потоков #7
Цитата Сообщение от Praktolock Посмотреть сообщение
Не не, не так, пишет только 1, читает только 1
По коду я не вижу, чтобы это где-то гарантировалось.
Praktolock
 Аватар для Praktolock
58 / 58 / 0
Регистрация: 29.11.2011
Сообщений: 272
15.06.2014, 15:35  [ТС]     Буферы и синхронизация потоков #8
2 флага: rbisy - означает, что буфер занят тем что в него пишут, wbisy - читают.
А по коду можно не увидеть, т.к. он же впринципе не рабочий) Я и сам уже это вижу
0x10
2425 / 1597 / 232
Регистрация: 24.11.2012
Сообщений: 3,919
15.06.2014, 15:37     Буферы и синхронизация потоков #9
Praktolock, функции захвата этого самопального мьютекса неатомрны, что я и показал на примере выше.
Praktolock
 Аватар для Praktolock
58 / 58 / 0
Регистрация: 29.11.2011
Сообщений: 272
15.06.2014, 15:39  [ТС]     Буферы и синхронизация потоков #10
Я убежден, что им вовсе не обязательно быть таковыми
0x10
2425 / 1597 / 232
Регистрация: 24.11.2012
Сообщений: 3,919
15.06.2014, 15:41     Буферы и синхронизация потоков #11
Цитата Сообщение от Praktolock Посмотреть сообщение
Я убежден, что им вовсе не обязательно быть таковыми
Happy debugging.
Убежденный
Системный программист
 Аватар для Убежденный
14191 / 6206 / 985
Регистрация: 02.05.2013
Сообщений: 10,339
Завершенные тесты: 1
15.06.2014, 15:43     Буферы и синхронизация потоков #12
Цитата Сообщение от Praktolock Посмотреть сообщение
Не не, не так, пишет только 1, читает только 1. Они не будут оба пытаться писать
Это ничего принципиально не меняет.
Поток А входит в gonnaread, видит, что wbisy равен нулю и получает
доступ на чтение. В это же время поток Б входит в gonnawrite, видит,
что rbisy тоже обнулен и получает доступ на запись. Гонка!

Не по теме:


Правильно "busy", а не "bisy".



Кстати, запись "while (var > 0)" легко может быть соптимизирована
компилятором до чтения var из регистра, в результате чего поток вообще
никогда не выйдет из цикла. Так что здесь еще нужно дополнительное
условие (например, volatile), чтобы цикл заработал как требуется.
Praktolock
 Аватар для Praktolock
58 / 58 / 0
Регистрация: 29.11.2011
Сообщений: 272
15.06.2014, 15:54  [ТС]     Буферы и синхронизация потоков #13
А если так?
C++
1
2
3
4
5
6
7
8
9
10
11
void STBUFFER::gonnawrite()
{
 wbisy++;
 while(rbisy>0){/*какаянибудь пурга*/};
};
 
void STBUFFER::gonnaread()
{
 rbisy++;
 while(wbisy>0){/*какаянибудь пурга*/};
};
Добавлено через 3 минуты
а нет, тоже фигня. Совсем чота сварить не могу
Убежденный
Системный программист
 Аватар для Убежденный
14191 / 6206 / 985
Регистрация: 02.05.2013
Сообщений: 10,339
Завершенные тесты: 1
15.06.2014, 15:59     Буферы и синхронизация потоков #14
Вместо rbisy++ и wbisy++ можно использовать "Compare and swap" (CAS).
Например, в Windows это будет InterlockedCompareExchange. Атомарно.
Но это уже платформенные средства...
0x10
2425 / 1597 / 232
Регистрация: 24.11.2012
Сообщений: 3,919
15.06.2014, 16:01     Буферы и синхронизация потоков #15
У gcc есть встроенные атомарные функции - http://gcc.gnu.org/onlinedocs/gcc-4....-Builtins.html
Опять же - только для одного компилятора.
Простая известная вещь - доступ к разделяемым ресурсам нужно контролировать. std::mutex и все около него в помощь, выше уже упоминали.
Praktolock
 Аватар для Praktolock
58 / 58 / 0
Регистрация: 29.11.2011
Сообщений: 272
15.06.2014, 16:34  [ТС]     Буферы и синхронизация потоков #16
Алгоритм Деккера заиспользую короче, и не буду париться
Убежденный
Системный программист
 Аватар для Убежденный
14191 / 6206 / 985
Регистрация: 02.05.2013
Сообщений: 10,339
Завершенные тесты: 1
15.06.2014, 16:39     Буферы и синхронизация потоков #17
Цитата Сообщение от Praktolock Посмотреть сообщение
Алгоритм Деккера заиспользую короче, и не буду париться
Про барьеры не забудьте.
Praktolock
 Аватар для Praktolock
58 / 58 / 0
Регистрация: 29.11.2011
Сообщений: 272
16.06.2014, 02:33  [ТС]     Буферы и синхронизация потоков #18
Ну короче вот так:

buffer.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <vector>
 
struct STBUFFER
{
 
 std::vector<char>data;
 volatile int rbusy;
 volatile int wbusy;
 volatile int turn;
 STBUFFER();
 void gonnawrite();
 void gonnaread ();
 void finishedwrite();
 void finishedread ();
 
 int read (char*, int);
 int write(char*, int);
};
buffer.cpp
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include "buffer.h"
 
STBUFFER::STBUFFER()
{
 rbusy=0;
 wbusy=0;
 turn =0;
};
 
void STBUFFER::gonnawrite()
{
 wbusy=1;
 while(rbusy)
 {
  if(!turn)
  {
   wbusy=0;
   while(!turn){/*sleep*/};
   wbusy=1;
  }
 }
};
 
void STBUFFER::finishedwrite()
{
 wbusy=0;
 turn=0;
};
 
void STBUFFER::gonnaread()
{
 rbusy=1;
 while(wbusy)
 {
  if(turn)
  {
   rbusy=0;
   while(turn){/*sleep*/};
   rbusy=1;
  }
 }
};
 
void STBUFFER::finishedread()
{
 rbusy=0;
 turn=1;
};
 
int STBUFFER::read(char*_buf, int _sz)
{
 gonnaread();
 //читаем
 finishedread();
 return(0);
};
 
int STBUFFER::write(char*_buf, int _sz)
{
 gonnawrite();
 //пишем
 finishedwrite();
 return(0);
};
Не смог придумать адекватного названия переменной turn.
Убежденный
Системный программист
 Аватар для Убежденный
14191 / 6206 / 985
Регистрация: 02.05.2013
Сообщений: 10,339
Завершенные тесты: 1
16.06.2014, 08:31     Буферы и синхронизация потоков #19
Цитата Сообщение от Praktolock
C++
1
2
wbusy=1;
while(rbusy)
На IA-32/AMD64 эта конструкция не гарантирует нужный эффект.
Дело в том, что CPU может выполнять последовательность "чтение-запись" в
обратном порядке. И получится здесь проверка rbusy раньше, чем установка
wbusy в 1. Между этими строками (и не только здесь) нужно вставить
хардварный барьер. И снова мы выходим на платформенные рельсы...
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
16.06.2014, 08:42     Буферы и синхронизация потоков
Еще ссылки по теме:

C++ Создание и завершение процессов и потоков. Приоритеты выполнения потоков
Синхронизация потоков на семафорах C++
Синхронизация потоков - уведомление о событии C++

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

Или воспользуйтесь поиском по форуму:
Praktolock
 Аватар для Praktolock
58 / 58 / 0
Регистрация: 29.11.2011
Сообщений: 272
16.06.2014, 08:42  [ТС]     Буферы и синхронизация потоков #20
Цитата Сообщение от Убежденный Посмотреть сообщение
И получится здесь проверка rbusy раньше, чем установка
wbusy в 1.
Ну и ладно.

C++
1
2
3
4
5
6
7
8
9
10
11
12
void STBUFFER::gonnaread()
{
 while(wbusy)
 {
  rbusy=1;
  if(turn)
  {
   rbusy=0;
   while(turn){/*sleep*/};
   rbusy=1;
  }
 }
Даже так работать должно жеж

Добавлено через 54 секунды
или нет?
Yandex
Объявления
16.06.2014, 08:42     Буферы и синхронизация потоков
Ответ Создать тему
Опции темы

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