Tark_Wight

Untitled

Apr 15th, 2023
134
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.33 KB | None | 0 0
  1. #include <Windows.h>
  2. #include <iostream>
  3. #include <thread>
  4. #include <Windows.h>
  5. #include <mutex>
  6. #include <string>
  7. #include <vector>
  8. #include <ctime>
  9. #include <chrono>
  10. #include <bits/stdc++.h>
  11. #include <random>
  12. #include <algorithm> // for copy
  13. #include <iterator> // for ostream_iterator
  14. using namespace std;
  15. bool stop = false;
  16. BOOL WINAPI CtrlHandler(DWORD fdwCtrlType) {
  17. switch (fdwCtrlType){
  18. case CTRL_C_EVENT:
  19. cout << "SIGINT signal received!" << endl;
  20. cout << "Stopping generator and all devices" << endl;
  21. cout.flush();
  22. stop = true;
  23. return TRUE;
  24. default:
  25. return FALSE;
  26. }}
  27. struct Request {
  28. int requestClass, type;
  29. };
  30. unsigned int RandomBetween(const int nMin, const int nMax){
  31. std::random_device seeder;
  32. std::mt19937 engine(seeder());
  33. std::uniform_int_distribution<int> dist(nMin, nMax);
  34. return dist(engine);
  35. }
  36. void clear_screen (void)
  37. {
  38. DWORD n;
  39. DWORD size;
  40. COORD coord = {0};
  41. CONSOLE_SCREEN_BUFFER_INFO csbi;
  42. HANDLE h = GetStdHandle ( STD_OUTPUT_HANDLE );
  43. GetConsoleScreenBufferInfo ( h, &csbi );
  44. size = csbi.dwSize.X * csbi.dwSize.Y;
  45. FillConsoleOutputCharacter ( h, TEXT ( ' ' ), size, coord, &n );
  46. GetConsoleScreenBufferInfo ( h, &csbi );
  47. FillConsoleOutputAttribute ( h, csbi.wAttributes, size, coord, &n );
  48. SetConsoleCursorPosition ( h, coord );
  49. }
  50. void printHelp(const std::string& name = ""){
  51. string help = "Usage: \n"
  52. "\t" + name + " queue_length groups_num group_capacity\n"
  53. "EVERY argument is required\n\n"
  54. "\tqueue_length > 0\n"
  55. "\tgroups_num, group_capacity >= 2\n"
  56. "add \"debug\" flag to print queue\n";
  57. cout << help << endl;
  58. }
  59. void Enqueue(vector<Request> &queue, Request &request) {
  60. if (queue.empty()) //если очередь пуста, просто добавляем в вектор заявку
  61. queue.push_back(request); //формат заявки выше
  62. else {
  63. for (int index = 0; index < queue.size(); index++){
  64. if (queue[index].type < request.type) {
  65. queue.insert(queue.begin() + index, request);
  66. break;
  67. }
  68. }
  69. }
  70. }
  71. void Device(int groupNumber, int threadId, vector<Request> &queue, mutex &queueMutex, vector<string> &status) {
  72. bool isBusy = false;
  73. while (!stop) {
  74. isBusy = false;
  75. int type;
  76. string threadStatus;
  77. queueMutex.lock();
  78. if (!queue.empty()) {
  79. for (int i = 0; i < queue.size() && !isBusy; i++) {
  80. if (queue[i].requestClass == groupNumber) {
  81. type = queue[i].type;
  82. queue.erase(queue.begin() + i);
  83. isBusy = true;
  84. }
  85. }
  86. }
  87. queueMutex.unlock();
  88. int sleepTime = RandomBetween(64, 1024);
  89. threadStatus = "Device thread " + to_string(threadId);
  90. threadStatus += isBusy ? " is working on task of type " + to_string(type) + " for " + to_string(sleepTime) + " ms"
  91. : " is vacant";
  92. status[threadId] = threadStatus;
  93. this_thread::sleep_for(chrono::milliseconds(sleepTime)); // поток прибора засыпает на случайное время
  94. }
  95. }
  96. Request prepareRequest(int groupsCount){
  97. return Request {
  98. .requestClass = static_cast<int>(RandomBetween(0, groupsCount - 1)),
  99. .type = static_cast<int>(RandomBetween(1, 3)),
  100. };
  101. }
  102. void generator(int groupsCount, vector<Request> &queue, int &capacity, mutex &queueMutex, vector<string> &status) {
  103. while (!stop) {
  104. string generatorStatus;
  105. queueMutex.lock();проверок и добавления заявок
  106. if (queue.size() < capacity) {
  107. Request request = prepareRequest(groupsCount);
  108. Enqueue(queue, request);
  109. generatorStatus = to_string(queue.size()) + " request(s) in queue";
  110. }
  111. queueMutex.unlock(); //разблокируем очередь
  112. status[status.size() - 1] = generatorStatus;
  113. this_thread::sleep_for(chrono::milliseconds(RandomBetween(16, 128)));
  114.  
  115. }
  116. }
  117. void printQueue(mutex &queueMutex, const vector<Request> &queue) {
  118. cout << "\nQueue content:" << endl;
  119. queueMutex.lock();
  120. for(vector<int>::size_type i = 0; i != queue.size(); i++) {
  121. cout << "Request " << i << " is type: " << queue[i].type << "; class: " << queue[i].requestClass << endl;
  122. }
  123. cout.flush();
  124. queueMutex.unlock();
  125. }
  126. void printStatus(int groupsCount, int deviceCount, const vector<string> &status) {
  127. for (int i = 0; i < groupsCount * deviceCount + 1; i++) {
  128. cout << status[i] << endl;
  129. }
  130. cout.flush();
  131. }
  132. int main(int argc, char *argv[]) {
  133. srand(time(0));
  134. setlocale(LC_ALL, "rus");
  135. int capacity, groupsCount, deviceCount;
  136. capacity = argc > 1 ? atoi(argv[1]) : -1;
  137. groupsCount = argc > 2 ? atoi(argv[2]) : -1;
  138. deviceCount = argc > 3 ? atoi(argv[3]) : -1;
  139. bool DEBUG = argc > 4 && std::string(argv[4]) == "debug";
  140. if (capacity <= 0 || groupsCount < 2 || deviceCount < 2){
  141. printHelp("MultiThreading.exe");
  142. return 1;
  143. }
  144.  
  145. mutex queueMutex;
  146. vector<Request> queue;
  147. vector<string> status(groupsCount * deviceCount + 1, ""); /
  148. if (!SetConsoleCtrlHandler(CtrlHandler, TRUE)) {
  149. return -1;
  150. }
  151. vector<thread> deviceThread(groupsCount * deviceCount);
  152. for (int i = 0; i < groupsCount * deviceCount; i++) {
  153. deviceThread[i] = thread(Device, (int) i / deviceCount, i, ref(queue), ref(queueMutex), ref(status));
  154. }
  155. thread gen(generator, ref(groupsCount), ref(queue), ref(capacity), ref(queueMutex), ref(status));
  156. while (!stop) {
  157. clear_screen();
  158. printStatus(groupsCount, deviceCount, status);
  159. if (DEBUG) printQueue(queueMutex, queue);
  160. this_thread::sleep_for(chrono::milliseconds(200));
  161. }
  162. gen.join();
  163. cout << "Generator thread stopped" << endl;
  164. for (int i = 0; i < groupsCount * deviceCount; i++) {
  165. deviceThread[i].join();
  166. cout << "Device " << i << " thread stopped" << endl;
  167. }
  168. return 0;
  169. }
Advertisement
Add Comment
Please, Sign In to add comment