Facebook
From Scribby Gibbon, 1 Month ago, written in C++.
Embed
Download Paste or View Raw
Hits: 28
  1. #include "stdafx.h"
  2. #include <cstdlib>
  3. #include <iostream>
  4. #include <windows.h>
  5. #include <ctime>
  6. #include <conio.h>
  7.  
  8. using namespace std;
  9.  
  10. struct TMySemaphore {           //Наш семафор
  11.     HANDLE HEvent;//Событие
  12.     int Count;//Сколько ещё можно внести потоков
  13.     int Max;//Макс. кол-во
  14.     int waiting;//Сколько ждет
  15. }       Sem;
  16. HANDLE h[5];    //Дескрипторы потоков
  17. LPDWORD d[5];//Идентификаторы потоков
  18. int q[10];//Общий ресурс(массив)
  19. int i;
  20. DWORD dwError;
  21. LPTSTR hlocal;
  22. HANDLE ex;
  23. int    ipex,k;
  24.  
  25. void CreateMySemaphore(TMySemaphore *S, int init, int max, string name) {
  26.     S->Count = init;//Сколько еще может войти потоков(создаётся счётчик)
  27.     S->Max = max;//Макс. число потоков, которое может войти
  28.     if (init > max) {
  29.         cout << "Начальное значение должно быть меньше максимального\n" << GetLastError();
  30.         _getch();
  31.     }
  32.     S->HEvent = CreateEvent(NULL, false, true, (LPCWSTR)&name);//Создаём событие
  33.     S->waiting = 0;     //Сколько ждет
  34. }
  35.  
  36. void WaitForMySemaphore(TMySemaphore *S) {//Ждём семафора
  37.     if (S->Count > 0) {//Если еще может кто-то войти
  38.         S->Count--;//Уменьшаем
  39.  
  40.     }
  41.     else {
  42.         S->waiting++;//Увел. число ждущих
  43.  
  44.         ex = (HANDLE)GetCurrentThreadId();//получаем идентификатор потокf
  45.         for (k = 0; k <= 4; k++) {//Ищем номер потока
  46.             if (d[k] == ex ) ipex = k;
  47.         }
  48.         printf("Поток %d ждёт \n",ipex);
  49.  
  50.         WaitForSingleObject(S->HEvent, INFINITE);//Ждём, когда кто-нибудь просигналит событие(освободит семафор)
  51.     }
  52. }
  53.  
  54. void ReleaseMySemaphore(TMySemaphore *S) {//Освоб. семафор
  55.     if (S->Count == 0) {//Если заполнено
  56.         SetEvent(S->HEvent);//Сигналим событие
  57.     }
  58.     if (S->waiting > 0) {//Если кто-то ждет
  59.         S->waiting--;//Уменьшаем число ждущих
  60.  
  61.     }
  62.     else {
  63.         S->Count++;//Увел. число возможных потоков
  64.     }
  65.     if (S->Count > S->Max) {
  66.         cout << "Слишком много свободных!!!\n";
  67.     }
  68. }
  69.  
  70. void CloseMySemaphore(TMySemaphore *S) {//Закрываем семафор
  71.     CloseHandle(S->HEvent);//Закрываем дескриптор события
  72. }
  73.  
  74. DWORD proc1() {//Процедура добавляющих потоков
  75.     int x, i, j, ip;
  76.     HANDLE id;
  77.  
  78.     id = (HANDLE)GetCurrentThreadId();//получаем идентификатор потока
  79.     ip = 0;//Пока еще не нашли
  80.     for (i = 0; i <= 4; i++) {//Ищем номер потока
  81.         if (d[i] == id) ip = i;
  82.     }
  83.     for (i = 0; i <= 4; i++) {//Меняем пять чисел
  84.  
  85.  
  86.         printf("Поток %d Свободно в семафоре: %d  Ожидает в семафоре :%d \n", ip, Sem.Count, Sem.waiting);
  87.  
  88.  
  89.         WaitForMySemaphore(&Sem);//Ждем семафора
  90.         Sleep(3000);//задержка(3 сек.)
  91.         printf("Поток %d Свободно в семафоре: %d  Ожидает в семафоре :%d \n", ip, Sem.Count, Sem.waiting);
  92.  
  93.         j = rand() % 10;//[0..9]
  94.         x = rand() % 100;
  95.         //Пишем, какое число мы заменил
  96.         cout << "Поток " << ip << " Поток#" << ip << " заменил число под номером:" << j << "-" << x << "\n";
  97.         q[j] = x;//Меняем в массиве сл. число на сл. месте
  98.  
  99.         Sleep(2000);
  100.         ReleaseMySemaphore(&Sem);//Освоб семафор
  101.         printf("Поток %d Освобождён \n", ip);
  102.         printf("Поток %d - Свободно в семафоре: %d  Ожидает в семафоре :%d \n", ip, Sem.Count, Sem.waiting);
  103.  
  104.     }
  105.     return 0;
  106. }
  107.  
  108. DWORD proc2() {//процедура вынимающего потока
  109.     int i, j, x, ip;
  110.     LPDWORD id;
  111.  
  112.     id = (LPDWORD)GetCurrentThreadId();//получаем идентификатор потока
  113.     ip = 0;
  114.     for (i = 0; i <= 4; i++) {//Ищем номер потока
  115.         if (d[i] == id) ip = i;
  116.     }
  117.     for (i = 0; i <= 9; i++) {//смотрим случайный элемент массива
  118.                                //Состояние семафора
  119.  
  120.         printf("Поток %d - Свободно в семафоре: %d  Ожидает в семафоре :%d \n", ip, Sem.Count, Sem.waiting);
  121.  
  122.  
  123.         WaitForMySemaphore(&Sem);//Ждём семафора
  124.         Sleep(2000);
  125.         printf("Поток %d - Свободно в семафоре: %d  Ожидает в семафоре :%d \n", ip, Sem.Count, Sem.waiting);
  126.  
  127.         j = rand() % 10; //Место
  128.         x = q[j];//Вынимаем число из массива
  129.  
  130.         cout << "Поток " << ip << " Поток#" << ip << " получил число из места:" << j << "-" << x << "\n";
  131.  
  132.  
  133.         Sleep(2000);
  134.         ReleaseMySemaphore(&Sem);//Освоб. семафор
  135.         printf("Поток %d Освобождён \n", ip);
  136.         printf("Поток %d - Свободно в семафоре: %d  Ожидает в семафоре :%d \n", ip, Sem.Count, Sem.waiting);
  137.  
  138.     }
  139.     return 0;
  140. }
  141.  
  142.  
  143. int main() {//Основная программа
  144.     setlocale(LC_ALL, "russian_russia");
  145.     srand(time(NULL));
  146.  
  147.  
  148.     cout << "Исходный массив:";
  149.     for (i = 0; i <= 9; i++) {//Заполняем и выводим массив
  150.         q[i] = rand() % 100;
  151.         cout << q[i] << " ";
  152.     }
  153.     cout << "\n";
  154.     CreateMySemaphore(&Sem, 1, 1, "EventSemaphore");//Созд. семафор
  155.  
  156.     for (i = 0; i <= 2; i++) {
  157.         h[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)proc1, NULL, 0, (LPDWORD)&d[i]);//Создаём 3 кладущих потока
  158.         if (h[i] == 0)  cout << (GetLastError());
  159.          Sleep(500);
  160.  
  161.     }
  162.  
  163.    Sleep(1000);
  164.     for (i = 3; i <= 4; i++) {
  165.         h[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)proc2, NULL, 0, (LPDWORD)&d[i]);//Создаём 2 вынимающих потока
  166.         dwError = GetLastError();
  167.         if (h[i] == 0) cout << (dwError);
  168.         Sleep(500);
  169.  
  170.     }
  171.     WaitForMultipleObjects(5, &h[0], true, INFINITE);//Ждём завершения всех потоков
  172.     for (i = 0; i <= 4; i++) {
  173.         CloseHandle(h[i]);//Закрываем дескрипторы потоков
  174.     }
  175.  
  176.     CloseMySemaphore(&Sem);//Закрываем семафор
  177.     cout << "Полученный массив:"; //то, что получилось
  178.     for (i = 0; i <= 9; i++) { //Выводим массив
  179.         cout << q[i] << " ";
  180.     }
  181.     fflush(stdout);
  182.     _getch();
  183.     return 0;
  184.  
  185. }
  186.