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

C++

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 30, средняя оценка - 4.77
sergeyotro
0 / 0 / 0
Регистрация: 08.10.2011
Сообщений: 13
#1

Задача "Производители-Потребители", реализация с помощью Events и циклического буфера - C++

23.10.2011, 14:41. Просмотров 3879. Ответов 4
Метки нет (Все метки)

Доброго времени суток.

Написал программу для решения сабжевой задачи, с условиями 1 производитель, 1 потребитель.
Программа работает, потоки синхронизируются, тупиков не возникает.

Однако, условия поменялись и нужно изменить текст программы таким образом, что бы производителей было несколько, а потребитель один. Попытался реализовать такие условия, но не могу уместить в голове синхронизацию не только между производителем-потребителем, но и между производителями, что бы они делили буфер и не пытались туда писать одновременно.

В реализации этого условия и прошу помочь. Улучшения кода по первому условию так же приветствуется.

Ниже - текст программы с 1 производителем и 1 потребителем.
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include <iostream>
#include <conio.h>
#include <windows.h>
 
using namespace std;
 
unsigned long uThrProdID1, uThrConsID;
 
HANDLE hEventWrite, hEventRead;
HANDLE hThrProd1, hThrCons;
void ProducerThread(char name[11]);
void ConsumerThread(void *pParams);
 
#define SIZE_BUF 25
 
int cycleBuf[SIZE_BUF];
int tail = 0;
int head = 0;
int count = 0;
 
void FlushBuf(void);
void PutChar(int sym);
int GetChar(void);
 
int main()
{
    FlushBuf();
 
    hEventWrite = CreateEvent(NULL, FALSE, FALSE, NULL);
    hEventRead = CreateEvent(NULL, FALSE, TRUE, NULL);
 
    hThrProd1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ProducerThread, "Producer 1", 0, &uThrProdID1);
 
    hThrCons = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ConsumerThread, NULL, 0, &uThrConsID);
 
    getch();
    return 0;
}
 
void ProducerThread(char name[11])
{
    WaitForSingleObject(hEventRead, INFINITE);
    while(1)
    {
        Sleep(rand()%500);
 
        while (count < SIZE_BUF)
            PutChar(rand());
 
        cout <<  name << ": There are " << count << " symbols in buf" << endl << endl;
        SetEvent(hEventWrite);
    }
}
 
void ConsumerThread(void *pParams)
{
    WaitForSingleObject(hEventWrite, INFINITE);
    while(1)
    {
        Sleep(rand()%50);
 
        if (count == 0)
        {
            SetEvent(hEventRead);
            WaitForSingleObject(hEventWrite, INFINITE);
        }
 
        GetChar();
        cout << "Consumer: There are " << count << " symbols in buf now." << endl << endl;
    }
}
 
void FlushBuf(void)
{
    tail = 0;
    head = 0;
    count = 0;
}
 
void PutChar(int sym)
{
    if (count < SIZE_BUF)
    {
        cycleBuf[tail] = sym;
        count++;
        tail++;
        if (tail == SIZE_BUF) tail = 0;
    }
}
 
int GetChar(void)
{
    int sym = 0;
    if (count > 0)
    {
        sym = cycleBuf[head];
        count--;
        head++;
        if (head == SIZE_BUF) head = 0;
    }
    return sym;
}
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
23.10.2011, 14:41     Задача "Производители-Потребители", реализация с помощью Events и циклического буфера
Посмотрите здесь:
C++ Написать программу что меняло слово "кукушка" на "груша", с помощью стека
C++ Реализация класса "Студент" и наследование от него класса "Аспирант"
C++ Задача на нахождение "+" и "-" элементов в массиве
Необработанное исключение в "0x00a78659" в "First.exe": 0xC0000005: Нарушение прав доступа при записи "0x0189f000" Visual C++
C++ Необработанное исключение в "0x77913ab3" в "x": 0xC0000005: Нарушение прав доступа при чтении "0xdddddddd"
C++ Через ООП: Дать для числа наименование: "рубль", "рубля", "рублей";
Visual Studio не читает операторы, что начинаются на "glu" ("gluBuild2DMipmaps", "gluPerspective") C++
C++ Как отключить автоматическое добавление "_" "@" "number" к имени экстернального метода?
C++ Вывести на экран монитора число с наименованием "год","года", "лет"
Класс: Реализация через битовое поле класса "Множество" C++
C++ Собственная реализация паттерна "Слушатель" - нужна конструктивная критика

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

Или воспользуйтесь поиском по форуму:
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
niXman
Эксперт C++
3134 / 1446 / 49
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
23.10.2011, 20:08     Задача "Производители-Потребители", реализация с помощью Events и циклического буфера #2
Цитата Сообщение от sergeyotro Посмотреть сообщение
не могу уместить в голове синхронизацию не только между производителем-потребителем, но и между производителями
использую блокируемую очередь.
sergeyotro
0 / 0 / 0
Регистрация: 08.10.2011
Сообщений: 13
23.10.2011, 22:28  [ТС]     Задача "Производители-Потребители", реализация с помощью Events и циклического буфера #3
Цитата Сообщение от niXman Посмотреть сообщение
использую блокируемую очередь.
Спасибо за подсказку. Надеюсь я её правильно понял.

Вот код изменённой программы, работает правильно. Надеюсь, кому-нибудь пригодится.
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#include <iostream>
#include <conio.h>
#include <windows.h>
#define MAX_PRODUCERS 6
#define SIZE_BUF 25
//#define READ_OUTPUT
 
using namespace std;
 
DWORD uThrProdID[MAX_PRODUCERS], uThrConsID;
 
HANDLE hEventWrite, hEventRead, hEventBuf;
HANDLE hThrProdArray[MAX_PRODUCERS], hThrCons;
 
void ProducerThread(char name[11]);
void ConsumerThread(void *pParams);
 
int cycleBuf[SIZE_BUF];
int tail = 0;
int head = 0;
int count = 0;
 
void FlushBuf(void);
void PutChar(int sym);
int GetChar(void);
 
FILE *fw;
 
#ifdef READ_OUTPUT
FILE *fr;
#endif
 
int main()
{
    fw = fopen("bufw.txt", "w");
#ifdef READ_OUTPUT
    fr = fopen("bufr.txt", "w");
#endif
    FlushBuf();
 
    hEventWrite = CreateEvent(NULL, FALSE, FALSE, NULL);
    hEventBuf = CreateEvent(NULL, FALSE, TRUE, NULL);
    hEventRead = CreateEvent(NULL, FALSE, TRUE, NULL);
 
    for ( int i = 0; i < MAX_PRODUCERS; i++ )
    {
        char* prod = new char[11];
        sprintf(prod, "Producer %d", i+1);
        hThrProdArray[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ProducerThread, prod, 0, &uThrProdID[i]);
    }
 
    hThrCons = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ConsumerThread, NULL, 0, &uThrConsID);
 
    getch();
 
    fclose(fw);
#ifdef READ_OUTPUT
    fclose(fr);
#endif
 
    CloseHandle(hEventBuf);
    CloseHandle(hEventRead);
    CloseHandle(hEventWrite);
 
    for ( int i = 0; i < MAX_PRODUCERS; i++ )
        CloseHandle(hThrProdArray[i]);
 
    CloseHandle(hThrCons);
    return 0;
}
 
void ProducerThread(char name[11])
{
    while(1)
    {
        WaitForSingleObject(hEventRead, INFINITE);
        Sleep(rand()%500);
        if (count < SIZE_BUF)
        {
            for ( int i = 0; i < 3; i++ )
            {
                PutChar(name[9]);
                putc(name[9], fw);
            }
            putc(13, fw);
        }
        cout <<  name << ": There are " << count << " symbols in buf" << endl << endl;
        SetEvent(hEventWrite);
    }
}
 
void ConsumerThread(void *pParams)
{
    WaitForSingleObject(hEventWrite, INFINITE);
    while(1)
    {
        Sleep(rand()%50);
        if (count == 0)
        {
            SetEvent(hEventRead);
            WaitForSingleObject(hEventWrite, INFINITE);
        }
#ifdef READ_OUTPUT
        putc(GetChar(), fr);
#else
        GetChar();
#endif
        cout << "Consumer: I've read one symbol. There are " << count << " symbols in buf now. " << endl << endl;
        SetEvent(hEventRead);
    }
}
 
void FlushBuf(void)
{
    tail = 0;
    head = 0;
    count = 0;
}
 
void PutChar(int sym)
{
    WaitForSingleObject(hEventBuf, INFINITE);
    if (count < SIZE_BUF)
    {
        cycleBuf[tail] = sym;
        count++;
        tail++;
        if (tail == SIZE_BUF) tail = 0;
    }
    SetEvent(hEventBuf);
}
 
int GetChar(void)
{
    int sym = 0;
    if (count > 0)
    {
        sym = cycleBuf[head];
        count--;
        head++;
        if (head == SIZE_BUF) head = 0;
    }
    return sym;
}
niXman
Эксперт C++
3134 / 1446 / 49
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
23.10.2011, 23:55     Задача "Производители-Потребители", реализация с помощью Events и циклического буфера #4
Цитата Сообщение от sergeyotro Посмотреть сообщение
Надеюсь я её правильно понял.
ну почти... я имел ввиду написать обертку вокруг std::queue в которой push() и pop() защитить мьютексами.

твое решение тоже не плохое.
tanya234
Сообщений: n/a
08.04.2014, 18:51     Задача "Производители-Потребители", реализация с помощью Events и циклического буфера #5
а в какой среде вы разрабатывали?
Yandex
Объявления
08.04.2014, 18:51     Задача "Производители-Потребители", реализация с помощью Events и циклического буфера
Ответ Создать тему
Опции темы

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