Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <Windows.h>
- #include <iostream>
- #include <thread>
- #include <Windows.h>
- #include <mutex>
- #include <string>
- #include <vector>
- #include <ctime>
- #include <chrono>
- #include <bits/stdc++.h>
- #include <random>
- #include <algorithm> // for copy
- #include <iterator> // for ostream_iterator
- using namespace std;
- bool stop = false;
- BOOL WINAPI CtrlHandler(DWORD fdwCtrlType) {
- switch (fdwCtrlType){
- case CTRL_C_EVENT:
- cout << "SIGINT signal received!" << endl;
- cout << "Stopping generator and all devices" << endl;
- cout.flush();
- stop = true;
- return TRUE;
- default:
- return FALSE;
- }}
- struct Request {
- int requestClass, type;
- };
- unsigned int RandomBetween(const int nMin, const int nMax){
- std::random_device seeder;
- std::mt19937 engine(seeder());
- std::uniform_int_distribution<int> dist(nMin, nMax);
- return dist(engine);
- }
- void clear_screen (void)
- {
- DWORD n;
- DWORD size;
- COORD coord = {0};
- CONSOLE_SCREEN_BUFFER_INFO csbi;
- HANDLE h = GetStdHandle ( STD_OUTPUT_HANDLE );
- GetConsoleScreenBufferInfo ( h, &csbi );
- size = csbi.dwSize.X * csbi.dwSize.Y;
- FillConsoleOutputCharacter ( h, TEXT ( ' ' ), size, coord, &n );
- GetConsoleScreenBufferInfo ( h, &csbi );
- FillConsoleOutputAttribute ( h, csbi.wAttributes, size, coord, &n );
- SetConsoleCursorPosition ( h, coord );
- }
- void printHelp(const std::string& name = ""){
- string help = "Usage: \n"
- "\t" + name + " queue_length groups_num group_capacity\n"
- "EVERY argument is required\n\n"
- "\tqueue_length > 0\n"
- "\tgroups_num, group_capacity >= 2\n"
- "add \"debug\" flag to print queue\n";
- cout << help << endl;
- }
- void Enqueue(vector<Request> &queue, Request &request) {
- if (queue.empty()) //если очередь пуста, просто добавляем в вектор заявку
- queue.push_back(request); //формат заявки выше
- else {
- for (int index = 0; index < queue.size(); index++){
- if (queue[index].type < request.type) {
- queue.insert(queue.begin() + index, request);
- break;
- }
- }
- }
- }
- void Device(int groupNumber, int threadId, vector<Request> &queue, mutex &queueMutex, vector<string> &status) {
- bool isBusy = false;
- while (!stop) {
- isBusy = false;
- int type;
- string threadStatus;
- queueMutex.lock();
- if (!queue.empty()) {
- for (int i = 0; i < queue.size() && !isBusy; i++) {
- if (queue[i].requestClass == groupNumber) {
- type = queue[i].type;
- queue.erase(queue.begin() + i);
- isBusy = true;
- }
- }
- }
- queueMutex.unlock();
- int sleepTime = RandomBetween(64, 1024);
- threadStatus = "Device thread " + to_string(threadId);
- threadStatus += isBusy ? " is working on task of type " + to_string(type) + " for " + to_string(sleepTime) + " ms"
- : " is vacant";
- status[threadId] = threadStatus;
- this_thread::sleep_for(chrono::milliseconds(sleepTime)); // поток прибора засыпает на случайное время
- }
- }
- Request prepareRequest(int groupsCount){
- return Request {
- .requestClass = static_cast<int>(RandomBetween(0, groupsCount - 1)),
- .type = static_cast<int>(RandomBetween(1, 3)),
- };
- }
- void generator(int groupsCount, vector<Request> &queue, int &capacity, mutex &queueMutex, vector<string> &status) {
- while (!stop) {
- string generatorStatus;
- queueMutex.lock();проверок и добавления заявок
- if (queue.size() < capacity) {
- Request request = prepareRequest(groupsCount);
- Enqueue(queue, request);
- generatorStatus = to_string(queue.size()) + " request(s) in queue";
- }
- queueMutex.unlock(); //разблокируем очередь
- status[status.size() - 1] = generatorStatus;
- this_thread::sleep_for(chrono::milliseconds(RandomBetween(16, 128)));
- }
- }
- void printQueue(mutex &queueMutex, const vector<Request> &queue) {
- cout << "\nQueue content:" << endl;
- queueMutex.lock();
- for(vector<int>::size_type i = 0; i != queue.size(); i++) {
- cout << "Request " << i << " is type: " << queue[i].type << "; class: " << queue[i].requestClass << endl;
- }
- cout.flush();
- queueMutex.unlock();
- }
- void printStatus(int groupsCount, int deviceCount, const vector<string> &status) {
- for (int i = 0; i < groupsCount * deviceCount + 1; i++) {
- cout << status[i] << endl;
- }
- cout.flush();
- }
- int main(int argc, char *argv[]) {
- srand(time(0));
- setlocale(LC_ALL, "rus");
- int capacity, groupsCount, deviceCount;
- capacity = argc > 1 ? atoi(argv[1]) : -1;
- groupsCount = argc > 2 ? atoi(argv[2]) : -1;
- deviceCount = argc > 3 ? atoi(argv[3]) : -1;
- bool DEBUG = argc > 4 && std::string(argv[4]) == "debug";
- if (capacity <= 0 || groupsCount < 2 || deviceCount < 2){
- printHelp("MultiThreading.exe");
- return 1;
- }
- mutex queueMutex;
- vector<Request> queue;
- vector<string> status(groupsCount * deviceCount + 1, ""); /
- if (!SetConsoleCtrlHandler(CtrlHandler, TRUE)) {
- return -1;
- }
- vector<thread> deviceThread(groupsCount * deviceCount);
- for (int i = 0; i < groupsCount * deviceCount; i++) {
- deviceThread[i] = thread(Device, (int) i / deviceCount, i, ref(queue), ref(queueMutex), ref(status));
- }
- thread gen(generator, ref(groupsCount), ref(queue), ref(capacity), ref(queueMutex), ref(status));
- while (!stop) {
- clear_screen();
- printStatus(groupsCount, deviceCount, status);
- if (DEBUG) printQueue(queueMutex, queue);
- this_thread::sleep_for(chrono::milliseconds(200));
- }
- gen.join();
- cout << "Generator thread stopped" << endl;
- for (int i = 0; i < groupsCount * deviceCount; i++) {
- deviceThread[i].join();
- cout << "Device " << i << " thread stopped" << endl;
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment