Initial commit
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
cmake-build-debug/
|
||||||
19
CMakeLists.txt
Normal file
19
CMakeLists.txt
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.29)
|
||||||
|
project(os-labs)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 23)
|
||||||
|
|
||||||
|
add_executable(
|
||||||
|
os-labs
|
||||||
|
main.cpp
|
||||||
|
src/signal_handler.cpp
|
||||||
|
include/signal_handler.h
|
||||||
|
include/buffer.h
|
||||||
|
src/buffer.cpp
|
||||||
|
include/producer.h
|
||||||
|
src/consumer.cpp
|
||||||
|
include/consumer.h
|
||||||
|
src/producer.cpp
|
||||||
|
)
|
||||||
|
target_link_libraries(os-labs PRIVATE m)
|
||||||
|
target_include_directories(os-labs PRIVATE ${PROJECT_SOURCE_DIR}/include)
|
||||||
28
include/buffer.h
Normal file
28
include/buffer.h
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
//
|
||||||
|
// Created by lumijiez on 11/16/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef BUFFER_H
|
||||||
|
#define BUFFER_H
|
||||||
|
|
||||||
|
#include <queue>
|
||||||
|
#include <mutex>
|
||||||
|
#include <condition_variable>
|
||||||
|
|
||||||
|
class Buffer {
|
||||||
|
public:
|
||||||
|
explicit Buffer(int size);
|
||||||
|
void produce(int producerId, int item);
|
||||||
|
int consume(int consumerId);
|
||||||
|
bool isEmpty() const;
|
||||||
|
bool isFull() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::queue<int> items;
|
||||||
|
const int maxSize;
|
||||||
|
mutable std::mutex mtx;
|
||||||
|
std::condition_variable notFull;
|
||||||
|
std::condition_variable notEmpty;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //BUFFER_H
|
||||||
22
include/consumer.h
Normal file
22
include/consumer.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
//
|
||||||
|
// Created by lumijiez on 11/16/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef CONSUMER_H
|
||||||
|
#define CONSUMER_H
|
||||||
|
|
||||||
|
#include "buffer.h"
|
||||||
|
#include <semaphore>
|
||||||
|
|
||||||
|
class Consumer {
|
||||||
|
public:
|
||||||
|
Consumer(int id, Buffer& buffer, std::counting_semaphore<5>& sem);
|
||||||
|
void run() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int id;
|
||||||
|
Buffer& buffer;
|
||||||
|
std::counting_semaphore<5>& consumerSem;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //CONSUMER_H
|
||||||
22
include/producer.h
Normal file
22
include/producer.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
//
|
||||||
|
// Created by lumijiez on 11/16/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef PRODUCER_H
|
||||||
|
#define PRODUCER_H
|
||||||
|
|
||||||
|
#include "buffer.h"
|
||||||
|
#include <semaphore>
|
||||||
|
|
||||||
|
class Producer {
|
||||||
|
public:
|
||||||
|
Producer(int id, Buffer& buffer, std::counting_semaphore<3>& sem);
|
||||||
|
void run() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int id;
|
||||||
|
Buffer& buffer;
|
||||||
|
std::counting_semaphore<3>& producerSem;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //PRODUCER_H
|
||||||
18
include/signal_handler.h
Normal file
18
include/signal_handler.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
//
|
||||||
|
// Created by lumijiez on 11/16/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SIGNAL_HANDLER_H
|
||||||
|
#define SIGNAL_HANDLER_H
|
||||||
|
#include <cmath>
|
||||||
|
#include <iostream>
|
||||||
|
#include <csignal>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <limits>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <bits/random.h>
|
||||||
|
#include <random>
|
||||||
|
void setupSignalHandlers();
|
||||||
|
|
||||||
|
#endif //SIGNAL_HANDLER_H
|
||||||
76
main.cpp
Normal file
76
main.cpp
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <thread>
|
||||||
|
#include <vector>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "signal_handler.h"
|
||||||
|
#include "buffer.h"
|
||||||
|
#include "producer.h"
|
||||||
|
#include "consumer.h"
|
||||||
|
|
||||||
|
[[noreturn]] void runSignalHandler() {
|
||||||
|
setupSignalHandlers();
|
||||||
|
std::cout << "PID: " << getpid() << std::endl;
|
||||||
|
while (true) {
|
||||||
|
pause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void runProducerConsumer() {
|
||||||
|
Buffer buffer(10);
|
||||||
|
std::counting_semaphore<3> producerSem(3);
|
||||||
|
std::counting_semaphore<5> consumerSem(5);
|
||||||
|
|
||||||
|
std::vector<std::thread> producers;
|
||||||
|
std::vector<std::thread> consumers;
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
producers.emplace_back([i, &buffer, &producerSem]() {
|
||||||
|
const Producer producer(i, buffer, producerSem);
|
||||||
|
producer.run();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
consumers.emplace_back([i, &buffer, &consumerSem]() {
|
||||||
|
const Consumer consumer(i, buffer, consumerSem);
|
||||||
|
consumer.run();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& p : producers) {
|
||||||
|
p.join();
|
||||||
|
}
|
||||||
|
for (auto& c : consumers) {
|
||||||
|
c.join();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
while (true) {
|
||||||
|
std::cout << "=== Main Menu ===\n";
|
||||||
|
std::cout << "1. Run Signal Handler Program\n";
|
||||||
|
std::cout << "2. Run Producer/Consumer Program\n";
|
||||||
|
std::cout << "0. Exit\n";
|
||||||
|
std::cout << "Enter your choice: ";
|
||||||
|
|
||||||
|
int choice;
|
||||||
|
std::cin >> choice;
|
||||||
|
|
||||||
|
switch (choice) {
|
||||||
|
case 1:
|
||||||
|
std::cout << "Running Signal Handler Program...\n";
|
||||||
|
runSignalHandler();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
std::cout << "Running Producer/Consumer Program...\n";
|
||||||
|
runProducerConsumer();
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
std::cout << "Exiting program. Goodbye!\n";
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
std::cout << "Invalid choice. Please try again.\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
40
src/buffer.cpp
Normal file
40
src/buffer.cpp
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
//
|
||||||
|
// Created by lumijiez on 11/16/24.
|
||||||
|
//
|
||||||
|
#include "buffer.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
Buffer::Buffer(const int size) : maxSize(size) {}
|
||||||
|
|
||||||
|
void Buffer::produce(const int producerId, const int item) {
|
||||||
|
std::unique_lock lock(mtx);
|
||||||
|
notFull.wait(lock, [this] { return !isFull(); });
|
||||||
|
|
||||||
|
items.push(item);
|
||||||
|
std::cout << "Producer " << producerId << " produced: " << item << std::endl;
|
||||||
|
|
||||||
|
lock.unlock();
|
||||||
|
notEmpty.notify_one();
|
||||||
|
}
|
||||||
|
|
||||||
|
int Buffer::consume(const int consumerId) {
|
||||||
|
std::unique_lock lock(mtx);
|
||||||
|
notEmpty.wait(lock, [this] { return !isEmpty(); });
|
||||||
|
|
||||||
|
const int item = items.front();
|
||||||
|
items.pop();
|
||||||
|
std::cout << "Consumer " << consumerId << " consumed: " << item << std::endl;
|
||||||
|
|
||||||
|
lock.unlock();
|
||||||
|
notFull.notify_one();
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Buffer::isEmpty() const {
|
||||||
|
return items.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Buffer::isFull() const {
|
||||||
|
return items.size() >= maxSize;
|
||||||
|
}
|
||||||
18
src/consumer.cpp
Normal file
18
src/consumer.cpp
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
//
|
||||||
|
// Created by lumijiez on 11/16/24.
|
||||||
|
//
|
||||||
|
#include "consumer.h"
|
||||||
|
#include <chrono>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
Consumer::Consumer(const int id, Buffer& buffer, std::counting_semaphore<5>& sem)
|
||||||
|
: id(id), buffer(buffer), consumerSem(sem) {}
|
||||||
|
|
||||||
|
void Consumer::run() const {
|
||||||
|
while (true) {
|
||||||
|
consumerSem.acquire();
|
||||||
|
int item = buffer.consume(id);
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||||
|
consumerSem.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
24
src/producer.cpp
Normal file
24
src/producer.cpp
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
//
|
||||||
|
// Created by lumijiez on 11/16/24.
|
||||||
|
//
|
||||||
|
#include "producer.h"
|
||||||
|
#include <random>
|
||||||
|
#include <chrono>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
Producer::Producer(const int id, Buffer& buffer, std::counting_semaphore<3>& sem)
|
||||||
|
: id(id), buffer(buffer), producerSem(sem) {}
|
||||||
|
|
||||||
|
void Producer::run() const {
|
||||||
|
std::random_device rd;
|
||||||
|
std::mt19937 gen(rd());
|
||||||
|
std::uniform_int_distribution<> dis(1, 100);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
producerSem.acquire();
|
||||||
|
const int item = dis(gen);
|
||||||
|
buffer.produce(id, item);
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||||
|
producerSem.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
27
src/signal_handler.cpp
Normal file
27
src/signal_handler.cpp
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// Created by lumijiez on 11/16/24.
|
||||||
|
//
|
||||||
|
#include "signal_handler.h"
|
||||||
|
|
||||||
|
void handleSignal(const int signal) {
|
||||||
|
if (signal == SIGUSR1) {
|
||||||
|
std::cout << "SIGUSR1 received" << std::endl;
|
||||||
|
} else if (signal == SIGUSR2) {
|
||||||
|
std::random_device rd;
|
||||||
|
std::default_random_engine generator(rd());
|
||||||
|
std::uniform_int_distribution distribution(32, 126);
|
||||||
|
|
||||||
|
for (int i = 0; i < 100; ++i) {
|
||||||
|
const char randomChar = static_cast<char>(distribution(generator));
|
||||||
|
std::cout << randomChar;
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
std::exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setupSignalHandlers() {
|
||||||
|
std::signal(SIGUSR1, handleSignal);
|
||||||
|
std::signal(SIGUSR2, handleSignal);
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user