Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.92/13: Рейтинг темы: голосов - 13, средняя оценка - 4.92
73 / 73 / 18
Регистрация: 29.11.2011
Сообщений: 356
1

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

15.06.2014, 14:36. Показов 2591. Ответов 21
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Всем привет. Суть такова: есть(будет) некая софтина которая подгружает плагины(дмнамические библиотеки) создает поток с функцией из этого плагина и весь обмен происходит через буферы, которые нужно блокировать ну чтобы там писать/читать одновременно нельзя было. Для каждого плагина ровно 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);
};
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
15.06.2014, 14:36
Ответы с готовыми решениями:

Синхронизация потоков в c++
Совершенно не понятно что не так и как правильно. Задача: Отсортировать массив целых чисел....

Синхронизация потоков
Снова привет. Есть у меня код, который требуется раскидать на потоки. Ниже код: #include...

синхронизация потоков
проблема в следующем: есть 2 потока один считает некоторую сумму в цикле по столбцам матрицы...

Синхронизация потоков - C++
Что это? Как это исправить? &quot;ConsoleApplication2.exe&quot; (Win32). Загружено...

21
3257 / 2059 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
15.06.2014, 14:50 2
1. Еще раз задуматься об архитектуре. Возможно ли обращение из нескольких потоков к потокам? Обязательно ли взаимодействие через потоки? Пока мотивации не вижу.
2. Свои велосипеды на выброс. Если и заработает, то как минимум, работать будет неэффективно. Циклами с ожиданием - только проц греть.
0
73 / 73 / 18
Регистрация: 29.11.2011
Сообщений: 356
15.06.2014, 14:57  [ТС] 3
Цитата Сообщение от 0x10 Посмотреть сообщение
Циклами с ожиданием - только проц греть.
он не будет пустым, там оставлено место под какойнибудь sleep, например
C++
1
while(wbisy>0){/*какаянибудь пурга*/};
Цитата Сообщение от 0x10 Посмотреть сообщение
1. Еще раз задуматься об архитектуре. Возможно ли обращение из нескольких потоков к потокам? Обязательно ли взаимодействие через потоки? Пока мотивации не вижу.
Только 1 поток может писать только в 1 буфер, и только он может читать только из 1 другого буфера. В то время как 2-ой поток можеть писать только в 1 буфер, в тот с которого читает первый поток, и только он один можеть читать с буфера в который можеть писать один единственный поток (1-й). как-то так. На мой взгляд, архитектура идеальна.
0
3257 / 2059 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
15.06.2014, 15:00 4
И да - работать не будет.

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

И вот у нас уже два потока ломятся на запись.
1
73 / 73 / 18
Регистрация: 29.11.2011
Сообщений: 356
15.06.2014, 15:27  [ТС] 5
Не не, не так, пишет только 1, читает только 1. Они не будут оба пытаться писать
0
2782 / 1935 / 570
Регистрация: 05.06.2014
Сообщений: 5,600
15.06.2014, 15:28 6
Не хочу использовать платформенно зависимые средства и буст тоже использовать не хочу.
std::mutex. Стандартная библиотека, однако.
1
3257 / 2059 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
15.06.2014, 15:32 7
Цитата Сообщение от Praktolock Посмотреть сообщение
Не не, не так, пишет только 1, читает только 1
По коду я не вижу, чтобы это где-то гарантировалось.
0
73 / 73 / 18
Регистрация: 29.11.2011
Сообщений: 356
15.06.2014, 15:35  [ТС] 8
2 флага: rbisy - означает, что буфер занят тем что в него пишут, wbisy - читают.
А по коду можно не увидеть, т.к. он же впринципе не рабочий) Я и сам уже это вижу
0
3257 / 2059 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
15.06.2014, 15:37 9
Praktolock, функции захвата этого самопального мьютекса неатомрны, что я и показал на примере выше.
0
73 / 73 / 18
Регистрация: 29.11.2011
Сообщений: 356
15.06.2014, 15:39  [ТС] 10
Я убежден, что им вовсе не обязательно быть таковыми
0
3257 / 2059 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
15.06.2014, 15:41 11
Цитата Сообщение от Praktolock Посмотреть сообщение
Я убежден, что им вовсе не обязательно быть таковыми
Happy debugging.
0
Ушел с форума
Эксперт С++
16473 / 7436 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
15.06.2014, 15:43 12
Цитата Сообщение от Praktolock Посмотреть сообщение
Не не, не так, пишет только 1, читает только 1. Они не будут оба пытаться писать
Это ничего принципиально не меняет.
Поток А входит в gonnaread, видит, что wbisy равен нулю и получает
доступ на чтение. В это же время поток Б входит в gonnawrite, видит,
что rbisy тоже обнулен и получает доступ на запись. Гонка!

Не по теме:


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



Кстати, запись "while (var > 0)" легко может быть соптимизирована
компилятором до чтения var из регистра, в результате чего поток вообще
никогда не выйдет из цикла. Так что здесь еще нужно дополнительное
условие (например, volatile), чтобы цикл заработал как требуется.
1
73 / 73 / 18
Регистрация: 29.11.2011
Сообщений: 356
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 минуты
а нет, тоже фигня. Совсем чота сварить не могу
0
Ушел с форума
Эксперт С++
16473 / 7436 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
15.06.2014, 15:59 14
Вместо rbisy++ и wbisy++ можно использовать "Compare and swap" (CAS).
Например, в Windows это будет InterlockedCompareExchange. Атомарно.
Но это уже платформенные средства...
0
3257 / 2059 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
15.06.2014, 16:01 15
У gcc есть встроенные атомарные функции - http://gcc.gnu.org/onlinedocs/... ltins.html
Опять же - только для одного компилятора.
Простая известная вещь - доступ к разделяемым ресурсам нужно контролировать. std::mutex и все около него в помощь, выше уже упоминали.
1
73 / 73 / 18
Регистрация: 29.11.2011
Сообщений: 356
15.06.2014, 16:34  [ТС] 16
Алгоритм Деккера заиспользую короче, и не буду париться
0
Ушел с форума
Эксперт С++
16473 / 7436 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
15.06.2014, 16:39 17
Цитата Сообщение от Praktolock Посмотреть сообщение
Алгоритм Деккера заиспользую короче, и не буду париться
Про барьеры не забудьте.
0
73 / 73 / 18
Регистрация: 29.11.2011
Сообщений: 356
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.
0
Ушел с форума
Эксперт С++
16473 / 7436 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
16.06.2014, 08:31 19
Цитата Сообщение от Praktolock
C++
1
2
wbusy=1;
while(rbusy)
На IA-32/AMD64 эта конструкция не гарантирует нужный эффект.
Дело в том, что CPU может выполнять последовательность "чтение-запись" в
обратном порядке. И получится здесь проверка rbusy раньше, чем установка
wbusy в 1. Между этими строками (и не только здесь) нужно вставить
хардварный барьер. И снова мы выходим на платформенные рельсы...
0
73 / 73 / 18
Регистрация: 29.11.2011
Сообщений: 356
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 секунды
или нет?
0
16.06.2014, 08:42
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
16.06.2014, 08:42
Помогаю со студенческими работами здесь

Синхронизация потоков
Есть статический класс к которому я хочу обращаться из разных потоков static class MyLog {...

Синхронизация потоков
На собеседовании поставили такую задачу: есть 3 потока, в каждом из которых вызывается функция, в...

Синхронизация потоков
Добрый день. Как синхронизировать потоки, чтобы вывод в stdout был поочередным: foo bar foo bar?...

Синхронизация процессов и потоков
Помогите с заданием, пожалуйста.

Синхронизация потоков Event c++
Необходимо, чтобы нить t4 ждала события просчета времени &quot;time = 1000 * (getTime() - time);&quot; и...

Синхронизация потоков на семафорах
почему не работает синхронизация потоков на семафорах? при компиляции ошибка сегментирования. На...


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

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