#include "stdafx.h"
#include <cstdlib>
#include <iostream>
#include <windows.h>
#include <ctime>
#include <conio.h>
using namespace std;
struct TMySemaphore { //Наш семафор
HANDLE HEvent;//Событие
int Count;//Сколько ещё можно внести потоков
int Max;//Макс. кол-во
int waiting;//Сколько ждет
} Sem;
HANDLE h[5]; //Дескрипторы потоков
int d[5];//Идентификаторы потоков
int q[10];//Общий ресурс(массив)
int i;
DWORD dwError;
LPTSTR hlocal;
void CreateMySemaphore(TMySemaphore S, int init,int max, string name) {
S.Count = init;//Сколько еще может войти потоков(создаётся счётчик)
S.Max = max;//Макс. число потоков, которое может войти
if (init > max) {
cout << "Start value must be less then maximal\n" << GetLastError();
_getch();
}
S.HEvent = CreateEvent(NULL, false, true, (LPCWSTR)&name);//Создаём событие
S.waiting = 0; //Сколько ждет
}
void WaitForMySemaphore(TMySemaphore S) {//Ждём семафора
if (S.Count > 0) {//Если еще может кто-то войти
S.Count--;//Уменьшаем
}
else {
S.waiting++;//Увел. число ждущих
WaitForSingleObject(S.HEvent, INFINITE);//Ждём, когда кто-нибудь просигналит событие(освободит семафор)
}
}
void ReleaseMySemaphore(TMySemaphore S) {//Освоб. семафор
if (S.Count == 0) {//Если заполнено
SetEvent(S.HEvent);//Сигналим событие
}
if (S.waiting > 0) {//Если кто-то ждет
S.waiting--;//Уменьшаем число ждущих
}
else {
S.Count++;//Увел. число возможных потоков
}
if (S.Count > S.Max) {
cout << "Too many!!!\n";
}
}
void CloseMySemaphore(TMySemaphore S) {//Закрываем семафор
CloseHandle(S.HEvent);//Закрываем дескриптор события
}
DWORD proc1(DWORD dd) {//Процедура добавляющих потоков
int x, i, j, ip;
DWORD id;
id = GetCurrentThreadId();//получаем идентификатор потока
ip = 0;//Пока еще не нашли
for (i = 1; i <= 5; i++) {//Ищем номер потока
if (d[i] == id) ip = i;
}
for (i = 1; i <= 5; i++) {//Меняем пять чисел
//Пишем состояние семафора
cout << ip << " Can enter:" << Sem.Count << " Are waiting:" << Sem.waiting << "\n";
cout << ip << " is waiting\n";
WaitForMySemaphore(Sem);//Ждем семафора
Sleep(1000);//задержка(1 сек.)
cout << ip << " Can enter:" << Sem.Count << " Are waiting:" << Sem.waiting << "\n";
j = (rand() % 10) + 1;//[1..10]
x = rand() % 100;
//Пишем, какое число мы заменили
cout << ip << " Thread#" << ip << " has put a number into place:" << j << "-" << x << "\n";
q[j] = x;//Меняем в массиве сл. число на сл. месте
cout << ip << " Can enter:" << Sem.Count << " Are waiting:" << Sem.waiting << "\n";
Sleep(1000);
ReleaseMySemaphore(Sem);//Освоб семафор
cout << ip << " Releasing\n";
cout << ip << " Can enter:" << Sem.Count << " Are waiting:" << Sem.waiting << "\n";
}
return 0;
}
DWORD proc2(DWORD dd) {//процедура вынимающего потока
int i, j, x, ip;
DWORD id;
id = GetCurrentThreadId();//получаем идентификатор потока
ip = 0;
for (i = 1; i <= 5; i++) {//Ищем номер потока
if (d[i] == id) ip = i;
}
for (i = 1; i <= 15; i++) {//смотрим случайный элемент массива
//Состояние семафора
cout << ip << " Can enter:" << Sem.Count << " Are waiting:" << Sem.waiting << "\n";
cout << ip << " Waiting\n";
WaitForMySemaphore(Sem);//Ждём семафора
Sleep(1000);
cout << ip << " Can enter:" << Sem.Count << " Are waiting:" << Sem.waiting << "\n";
j = (rand() % 10) + 1; //Место
x = q[j];//Вынимаем число из массива
//Какое число мы посмотрели
cout << ip << " Thread#" << ip << " has got a number from place:" << j << "-" << x << "\n";
cout << ip << " Can enter:" << Sem.Count << " Are waiting:" << Sem.waiting << "\n";
Sleep(1000);
ReleaseMySemaphore(Sem);//Освоб. семафор
cout << ip << " Releasing\n";
cout << ip << " Can enter:" << Sem.Count << " Are waiting:" << Sem.waiting << "\n";
}
return 0;
}
void main() {//Основная программа
setlocale(LC_ALL, "russian_russia");
srand(time(NULL));
//AllocConsole;//Создаем консоль
cout << "Was:";
for (i = 1; i <= 10; i++) {//Заполняем и выводим массив
q[i] = rand() % 100;
cout << q[i] << " ";
}
cout << "\n";
CreateMySemaphore(Sem, 3, 3, "EventSemaphore");//Созд. семафор
for (i = 1; i <= 3; i++) {
h[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)proc1, NULL, 0, (LPDWORD)d[i]);//Создаём 3 кладущих потока
if (h[i] == 0) cout << (GetLastError());
}
for (i = 4; i <= 5; i++) {
h[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)proc2, NULL, 0, (LPDWORD)d[i]);//Создаём 2 вынимающих потока
dwError = GetLastError();
if (h[i] == 0) cout << (dwError);
// FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ALLOCATE_BUFFER, nil, dwError; MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US); hlocal; 0; nil )
}
WaitForMultipleObjects(5, h,true, INFINITE);//Ждём завершения всех потоков
for (i = 1; i <= 5; i++) {
CloseHandle(h[i]);//Закрываем дескрипторы потоков
}
CloseMySemaphore(Sem);//Закрываем семафор
cout << "Is:"; //то, что получилось
for (i = 1; i <= 10; i++) { //Выводим массив
cout << q[i] << " ";
}
_getch();
//FreeConsole;//Закрываем консоль
}