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