diff options
| author | ckrinitsin <101062646+ckrinitsin@users.noreply.github.com> | 2025-03-21 15:20:21 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-03-21 15:20:21 +0100 |
| commit | 2a22b4123dce661b0500dc07012d61215bdce161 (patch) | |
| tree | 0e862837248107e4c0a323fffb2632da0bbb4482 /src | |
| parent | 5fee3dbc7341d2b6c4e72c0f56a121e1bd5553d9 (diff) | |
| parent | 4d0d9f183d7f92a41d66ffdcde15b040ff4032ef (diff) | |
| download | BT-Programming-Assignment-2a22b4123dce661b0500dc07012d61215bdce161.tar.gz BT-Programming-Assignment-2a22b4123dce661b0500dc07012d61215bdce161.zip | |
Merge pull request #3 from ckrinitsin/shm
Shared Memory Buffer
Diffstat (limited to '')
| -rw-r--r-- | src/client/main.cpp | 115 | ||||
| -rw-r--r-- | src/common/shared_memory.h | 46 | ||||
| -rw-r--r-- | src/server/main.cpp | 26 | ||||
| -rw-r--r-- | src/server/shared_memory_server.h | 96 |
4 files changed, 261 insertions, 22 deletions
diff --git a/src/client/main.cpp b/src/client/main.cpp new file mode 100644 index 0000000..6dfd48f --- /dev/null +++ b/src/client/main.cpp @@ -0,0 +1,115 @@ +#include "shared_memory.h" +#include <cstring> +#include <fcntl.h> +#include <iostream> +#include <pthread.h> +#include <sys/mman.h> +#include <unistd.h> +#include <utility> + +bool request_processed(SharedMemory* shared_memory, int index) +{ + if (shared_memory->full) { + return false; + } + if (shared_memory->tail == shared_memory->head && !shared_memory->full) { + return true; + } + + for (int i = shared_memory->head - 1; i != shared_memory->tail; i = (i - 1) % QUEUE_SIZE) { + if (i == index) { + return false; + } + } + + return shared_memory->tail != index; +} + +void send_request( + SharedMemory* shared_memory, + Operations type, + std::pair<const std::string&, const std::string&> arguments) +{ + int index; + + pthread_mutex_lock(&shared_memory->mutex); + + if (shared_memory->full) { + std::cout << "Queue is full" << '\n'; + pthread_cond_wait(&shared_memory->cond_var, &shared_memory->mutex); + return; + } + + index = shared_memory->head; + Request* request = &shared_memory->request[index]; + request->type = type; + strncpy(request->key, serialize(arguments.first).c_str(), MAX_KEY_SIZE); + strncpy(request->value, serialize(arguments.second).c_str(), MAX_VALUE_SIZE); + shared_memory->head = (1 + shared_memory->head) % QUEUE_SIZE; + shared_memory->full = shared_memory->head == shared_memory->tail; + pthread_cond_signal(&shared_memory->cond_var); + + pthread_mutex_unlock(&shared_memory->mutex); + + std::cout << "Command sent" << '\n'; + + if (type == Operations::GET) { + pthread_mutex_lock(&shared_memory->mutex); + + while (!request_processed(shared_memory, index)) { + pthread_cond_wait(&shared_memory->cond_var, &shared_memory->mutex); + } + std::string result(shared_memory->request[index].response); + pthread_mutex_unlock(&shared_memory->mutex); + std::cout << "Result: " << result << std::endl; + } +} + +int main() +{ + int shm_fd = shm_open(SHM_NAME, O_RDWR, 0666); + if (shm_fd == -1) { + std::cout << "Server not running" << '\n'; + return -1; + } + + SharedMemory* shared_memory = + (SharedMemory*)mmap(0, sizeof(SharedMemory), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); + + std::cout << "Start inserting.." << '\n'; + send_request(shared_memory, INSERT, std::pair(serialize(3), serialize(3))); + + std::cout << "Start inserting.." << '\n'; + send_request(shared_memory, INSERT, std::pair(serialize(4), serialize(5))); + + std::cout << "Start inserting.." << '\n'; + send_request(shared_memory, INSERT, std::pair(serialize(6), serialize(6))); + + std::cout << "Start inserting.." << '\n'; + send_request(shared_memory, INSERT, std::pair(serialize(7), serialize(3))); + + std::cout << "Start inserting.." << '\n'; + send_request(shared_memory, INSERT, std::pair(serialize(8), serialize(3))); + + std::cout << "Start inserting.." << '\n'; + send_request(shared_memory, INSERT, std::pair(serialize(9), serialize(3))); + + std::cout << "Start inserting.." << '\n'; + send_request(shared_memory, INSERT, std::pair(serialize(10), serialize(3))); + + std::cout << "Start inserting.." << '\n'; + send_request(shared_memory, INSERT, std::pair(serialize(11), serialize(3))); + + std::cout << "Start inserting.." << '\n'; + send_request(shared_memory, INSERT, std::pair(serialize(12), serialize(3))); + + std::cout << "Start inserting.." << '\n'; + send_request(shared_memory, INSERT, std::pair(serialize(13), serialize(4))); + + std::cout << "Start PRINTING.." << '\n'; + send_request(shared_memory, PRINT, std::pair(serialize(0), serialize(0))); + + munmap(shared_memory, sizeof(SharedMemory)); + close(shm_fd); + return 0; +} diff --git a/src/common/shared_memory.h b/src/common/shared_memory.h new file mode 100644 index 0000000..70554e4 --- /dev/null +++ b/src/common/shared_memory.h @@ -0,0 +1,46 @@ +#pragma once + +#include <pthread.h> +#include <sstream> + +#define SHM_NAME "/hashtable_queue" +#define QUEUE_SIZE 10 + +#define MAX_KEY_SIZE 64 +#define MAX_VALUE_SIZE 128 + +enum Operations { INSERT, DELETE, GET, PRINT }; + +struct Request { + Operations type; + char key[MAX_KEY_SIZE]; + char value[MAX_VALUE_SIZE]; + char response[MAX_VALUE_SIZE]; +}; + +struct SharedMemory { + Request request[QUEUE_SIZE]; + pthread_mutex_t mutex; + pthread_cond_t cond_var; + + int tail; + int head; + bool full; +}; + +template <typename T> +std::string serialize(const T& data) +{ + std::ostringstream oss; + oss << data; + return oss.str(); +} + +template <typename T> +T deserialize(const std::string& str) +{ + std::istringstream iss(str); + T data; + iss >> data; + return data; +} diff --git a/src/server/main.cpp b/src/server/main.cpp index b2f8bed..424326f 100644 --- a/src/server/main.cpp +++ b/src/server/main.cpp @@ -1,8 +1,9 @@ #include <cstdint> +#include <iostream> #include <stdexcept> #include <string> -#include "hashtable.h" +#include "shared_memory_server.h" int main(int argc, char* argv[]) { @@ -18,29 +19,10 @@ int main(int argc, char* argv[]) std::cout << "Invalid argument" << '\n'; return 1; } - - HashTable<int, std::string> hash_table { size }; - std::cout << "Add various kv-pairs" << '\n'; - hash_table.insert(1, "1"); - hash_table.insert(2, "2"); - hash_table.insert(3, "3"); - hash_table.insert(4, "4"); - hash_table.insert(5, "5"); - hash_table.insert(6, "6"); - hash_table.insert(7, "7"); + SharedMemoryServer<int, std::string> shm(size); - hash_table.print(); - - std::cout << '\n'; - - std::cout << "Value for key 8: " << hash_table.get(8).value_or("Key not found!") << '\n'; - std::cout << "Value for key 4: " << hash_table.get(4).value_or("Key not found!") << '\n'; - - std::cout << '\n'; - std::cout << "Remove pair with key 5" << '\n'; - hash_table.remove(5); - hash_table.print(); + shm.process_requests(); return 0; } diff --git a/src/server/shared_memory_server.h b/src/server/shared_memory_server.h new file mode 100644 index 0000000..74abedf --- /dev/null +++ b/src/server/shared_memory_server.h @@ -0,0 +1,96 @@ +#pragma once + +#include "hashtable.h" +#include "shared_memory.h" +#include <cstring> +#include <fcntl.h> +#include <optional> +#include <sys/mman.h> +#include <unistd.h> + +template <typename K, typename V> +class SharedMemoryServer { +public: + SharedMemoryServer(size_t size) + : hash_table(size) + { + shm_fd = shm_open(SHM_NAME, O_CREAT | O_RDWR, 0666); + + ftruncate(shm_fd, sizeof(SharedMemory)); + + shared_memory = (SharedMemory*) + mmap(0, sizeof(SharedMemory), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); + + shared_memory->tail = shared_memory->head = 0; + + pthread_mutexattr_t mutex_attr; + pthread_condattr_t cond_attr; + pthread_mutexattr_init(&mutex_attr); + pthread_mutexattr_setpshared(&mutex_attr, PTHREAD_PROCESS_SHARED); + pthread_condattr_init(&cond_attr); + pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED); + + pthread_mutex_init(&shared_memory->mutex, &mutex_attr); + pthread_cond_init(&shared_memory->cond_var, &cond_attr); + } + + ~SharedMemoryServer() + { + munmap(shared_memory, sizeof(SharedMemory)); + close(shm_fd); + shm_unlink(SHM_NAME); + } + + void process_requests() + { + while (true) { + pthread_mutex_lock(&shared_memory->mutex); + + if (shared_memory->tail == shared_memory->head && !shared_memory->full) { + pthread_cond_wait(&shared_memory->cond_var, &shared_memory->mutex); + } + + Request* request = &shared_memory->request[shared_memory->tail]; + + K key = deserialize<K>(request->key); + V value = deserialize<V>(request->value); + + switch (request->type) { + case INSERT: + std::cout << "Inserting" << '\n'; + hash_table.insert(key, value); + break; + case GET: { + std::cout << "Getting" << '\n'; + hash_table.insert(key, value); + std::optional<V> result = hash_table.get(key); + if (result.has_value()) { + std::string response = serialize<V>(result.value()); + strncpy(request->response, response.c_str(), MAX_VALUE_SIZE); + pthread_cond_signal(&shared_memory->cond_var); + } + break; + } + case DELETE: + std::cout << "Deleting" << '\n'; + hash_table.remove(key); + break; + case PRINT: + std::cout << "Printing" << '\n'; + hash_table.print(); + break; + default: + break; + } + shared_memory->tail = (1 + shared_memory->tail) % QUEUE_SIZE; + shared_memory->full = false; + pthread_mutex_unlock(&shared_memory->mutex); + } + } + +private: + HashTable<K, V> hash_table; + + int shm_fd; + SharedMemory* shared_memory; +}; |