From cc6cc494e388a8284ea2cfc08bd9d54e4ad38c7f Mon Sep 17 00:00:00 2001 From: Shivang Vijay Date: Thu, 22 Jun 2023 16:13:36 +0530 Subject: [PATCH 1/5] Implement v1.0.0 of Shared Memory --- concore.hpp | 228 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 224 insertions(+), 4 deletions(-) diff --git a/concore.hpp b/concore.hpp index 86e215c..3e1fe5c 100644 --- a/concore.hpp +++ b/concore.hpp @@ -12,15 +12,25 @@ //libraries for platform independent delay. Supports C++11 upwards #include #include +#include +#include +#include +#include +#include using namespace std; class Concore{ +private: //private variables string s="",olds=""; string inpath = "./in"; string outpath = "./out"; + int shmId_; + char* sharedData_; + // File sharing:- 0, Shared Memory:- 1 + int communication_ = 0; public: double delay = 1; @@ -32,9 +42,96 @@ class Concore{ //Constructor to put in iport and oport values in map Concore(){ iport = mapParser("concore.iport"); - oport = mapParser("concore.oport"); + oport = mapParser("concore.oport"); + std::map::iterator it_iport = iport.begin(); + std::map::iterator it_oport = oport.begin(); + int iport_number = AlphanumericSM(it_iport->first); + int oport_number = AlphanumericSM(it_oport->first); + + if(iport_number != -1 || oport_number != -1) + { + communication_ = 1; + if(iport_number > oport_number) + { + this->createSharedMemory(); + } + else + { + this->getSharedMemory(); + } + } + } + + /** + * return number if number is greater than zero + * and alphanumeric + */ + int AlphanumericSM(const std::string& input) { + bool isPureAlphabetic = true; + for (char c : input) { + if (!std::isalpha(c)) { + isPureAlphabetic = false; + break; + } + } + + if (isPureAlphabetic) { + return -1; + } else { + if (int(input[0])) + { + return int(input[0]); + } + return -1; + } } + ~Concore() + { + // Detach the shared memory segment from the process + shmdt(sharedData_); + + // Remove the shared memory segment + shmctl(shmId_, IPC_RMID, nullptr); + } + + + void createSharedMemory() + { + std::cout << "create SM" << std::endl; + shmId_ = shmget(1237, 256, IPC_CREAT | 0666); + if (shmId_ == -1) { + std::cerr << "Failed to create shared memory segment." << std::endl; + } + + // Attach the shared memory segment to the process's address space + sharedData_ = static_cast(shmat(shmId_, NULL, 0)); + if (sharedData_ == reinterpret_cast(-1)) { + std::cerr << "Failed to attach shared memory segment." << std::endl; + } + } + + void getSharedMemory() + { + std::cout << "get SM" << std::endl; + while (true) { + // Get the shared memory segment created by Writer + shmId_ = shmget(1237, 256, 0666); + + // Check if shared memory exists + if (shmId_ != -1) { + break; // Break the loop if shared memory exists + } + + std::cout << "Shared memory does not exist. Make sure the writer process is running." << std::endl; + sleep(1); // Sleep for 1 second before checking again + } + + // Attach the shared memory segment to the process's address space + sharedData_ = static_cast(shmat(shmId_, NULL, 0)); + } + + map mapParser(string filename){ map ans; @@ -112,8 +209,18 @@ class Concore{ return temp; } + vector read(int port, string name, string initstr) + { + if(communication_ == 1) + { + return read_SM(port, name, initstr); + } + + return read_FM(port, name, initstr); + } + //accepts the file name as string and returns a string of file content - vector read(int port, string name, string initstr){ + vector read_FM(int port, string name, string initstr){ chrono::milliseconds timespan((int)(1000*delay)); this_thread::sleep_for(timespan); string ins; @@ -159,6 +266,60 @@ class Concore{ } s += ins; + vector inval = parser(ins); + simtime = simtime > inval[0] ? simtime : inval[0]; + + //returning a string with data excluding simtime + inval.erase(inval.begin()); + return inval; + + } + + //accepts the file name as string and returns a string of file content + vector read_SM(int port, string name, string initstr){ + chrono::milliseconds timespan((int)(1000*delay)); + this_thread::sleep_for(timespan); + string ins = ""; + try { + if (shmId_ != -1) { + if (sharedData_ && sharedData_[0] != '\0') { + std::string message(sharedData_, strnlen(sharedData_, 256)); + ins = message; + std::cout << "Received message: " << message << " ins " << ins.length() << std::endl; + } + else + { + throw 505; + } + } + else + { + throw 505; + } + } catch (...) { + ins = initstr; + } + + while ((int)ins.length()==0){ + this_thread::sleep_for(timespan); + try{ + if(shmId_ != -1) { + std::cout << "in read while\n"; + std::string message(sharedData_, strnlen(sharedData_, 256)); + ins = message; + retrycount++; + } + else{ + retrycount++; + throw 505; + } + } + //observed retry count in C++ from various tests is approx 80. + catch(...){ + cout<<"Read error"; + } + } + s += ins; vector inval = parser(ins); simtime = simtime > inval[0] ? simtime : inval[0]; @@ -169,8 +330,28 @@ class Concore{ } + void write(int port, string name, vector val, int delta=0) + { + if(communication_ == 1) + { + return write_SM(port, name, val, delta); + } + + return write_FM(port, name, val, delta); + } + + void write(int port, string name, string val, int delta=0) + { + if(communication_ == 1) + { + return write_SM(port, name, val, delta); + } + + return write_FM(port, name, val, delta); + } + //write method, accepts a vector double and writes it to the file - void write(int port, string name, vector val, int delta=0){ + void write_FM(int port, string name, vector val, int delta=0){ try { ofstream outfile; @@ -194,7 +375,7 @@ class Concore{ } //write method, accepts a string and writes it to the file - void write(int port, string name, string val, int delta=0){ + void write_FM(int port, string name, string val, int delta=0){ chrono::milliseconds timespan((int)(2000*delay)); this_thread::sleep_for(timespan); try { @@ -211,6 +392,45 @@ class Concore{ cout<<"skipping +"< val, int delta=0){ + + try { + std::ostringstream outfile; + if(shmId_ != -1){ + val.insert(val.begin(),simtime+delta); + outfile<<'['; + for(int i=0;i initval(string f){ From 964855f5ac3c9b1164a99308544fe2fe1db50586 Mon Sep 17 00:00:00 2001 From: Shivang Vijay Date: Thu, 22 Jun 2023 17:09:55 +0530 Subject: [PATCH 2/5] commented not required print --- concore.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/concore.hpp b/concore.hpp index 3e1fe5c..aad248b 100644 --- a/concore.hpp +++ b/concore.hpp @@ -285,7 +285,7 @@ class Concore{ if (sharedData_ && sharedData_[0] != '\0') { std::string message(sharedData_, strnlen(sharedData_, 256)); ins = message; - std::cout << "Received message: " << message << " ins " << ins.length() << std::endl; + // std::cout << "Received message: " << message << " ins " << ins.length() << std::endl; } else { From 705ea429dea02c066fdd0f4444d6c71e7bb2b57c Mon Sep 17 00:00:00 2001 From: Shivang Vijay Date: Sun, 25 Jun 2023 15:35:33 +0530 Subject: [PATCH 3/5] Implemented multiple shared memory based on edge name --- concore.hpp | 147 +++++++++++++++++++++++++++++----------------------- 1 file changed, 81 insertions(+), 66 deletions(-) diff --git a/concore.hpp b/concore.hpp index aad248b..3f8797f 100644 --- a/concore.hpp +++ b/concore.hpp @@ -27,10 +27,15 @@ class Concore{ string s="",olds=""; string inpath = "./in"; string outpath = "./out"; - int shmId_; - char* sharedData_; + + int shmId_create; + int shmId_get; + + char* sharedData_create; + char* sharedData_get; // File sharing:- 0, Shared Memory:- 1 - int communication_ = 0; + int communication_iport = 0; + int communication_oport = 0; public: double delay = 1; @@ -45,81 +50,92 @@ class Concore{ oport = mapParser("concore.oport"); std::map::iterator it_iport = iport.begin(); std::map::iterator it_oport = oport.begin(); - int iport_number = AlphanumericSM(it_iport->first); - int oport_number = AlphanumericSM(it_oport->first); + int iport_number = generateNumberString(it_iport->first); + int oport_number = generateNumberString(it_oport->first); - if(iport_number != -1 || oport_number != -1) + if(oport_number != -1) { - communication_ = 1; - if(iport_number > oport_number) - { - this->createSharedMemory(); - } - else - { - this->getSharedMemory(); - } - } - } + communication_oport = 1; + this->createSharedMemory(oport_number); + } - /** - * return number if number is greater than zero - * and alphanumeric - */ - int AlphanumericSM(const std::string& input) { - bool isPureAlphabetic = true; - for (char c : input) { - if (!std::isalpha(c)) { - isPureAlphabetic = false; - break; - } - } - - if (isPureAlphabetic) { - return -1; - } else { - if (int(input[0])) - { - return int(input[0]); - } - return -1; - } + if(iport_number != -1) + { + communication_iport = 1; + this->getSharedMemory(iport_number); + } } ~Concore() { // Detach the shared memory segment from the process - shmdt(sharedData_); + shmdt(sharedData_create); + shmdt(sharedData_get); // Remove the shared memory segment - shmctl(shmId_, IPC_RMID, nullptr); + shmctl(shmId_create, IPC_RMID, nullptr); + } + + std::map createAlphabetMap() { + std::map alphabetMap; + + for (char c = 'A'; c <= 'Z'; ++c) { + alphabetMap[c] = c - 'A' + 1; + } + + return alphabetMap; } + key_t generateNumberString(const std::string& str) { + std::map alphabetMap = createAlphabetMap(); + std::string numberString; + + // Find the number of leading digits in the input string + size_t numDigits = 0; + std::string start_digit = ""; + while (numDigits < str.length() && std::isdigit(str[numDigits])) { + numberString += str[numDigits]; + ++numDigits; + } + + if (numDigits == 0) + { + return -1; + } - void createSharedMemory() + // Concatenate the numbers for the first three alphabet characters after the digits + for (size_t i = numDigits; i < str.length() && i < numDigits + 3; ++i) { + char c = std::toupper(str[i]); + if (alphabetMap.count(c) > 0) { + numberString += std::to_string(alphabetMap[c]); + } + } + + return std::stoi(numberString); + } + + void createSharedMemory(key_t key) { - std::cout << "create SM" << std::endl; - shmId_ = shmget(1237, 256, IPC_CREAT | 0666); - if (shmId_ == -1) { + shmId_create = shmget(key, 256, IPC_CREAT | 0666); + + if (shmId_create == -1) { std::cerr << "Failed to create shared memory segment." << std::endl; } // Attach the shared memory segment to the process's address space - sharedData_ = static_cast(shmat(shmId_, NULL, 0)); - if (sharedData_ == reinterpret_cast(-1)) { + sharedData_create = static_cast(shmat(shmId_create, NULL, 0)); + if (sharedData_create == reinterpret_cast(-1)) { std::cerr << "Failed to attach shared memory segment." << std::endl; } } - void getSharedMemory() + void getSharedMemory(key_t key) { - std::cout << "get SM" << std::endl; while (true) { // Get the shared memory segment created by Writer - shmId_ = shmget(1237, 256, 0666); - + shmId_get = shmget(key, 256, 0666); // Check if shared memory exists - if (shmId_ != -1) { + if (shmId_get != -1) { break; // Break the loop if shared memory exists } @@ -128,9 +144,8 @@ class Concore{ } // Attach the shared memory segment to the process's address space - sharedData_ = static_cast(shmat(shmId_, NULL, 0)); + sharedData_get = static_cast(shmat(shmId_get, NULL, 0)); } - map mapParser(string filename){ map ans; @@ -211,7 +226,7 @@ class Concore{ vector read(int port, string name, string initstr) { - if(communication_ == 1) + if(communication_iport == 1) { return read_SM(port, name, initstr); } @@ -281,9 +296,9 @@ class Concore{ this_thread::sleep_for(timespan); string ins = ""; try { - if (shmId_ != -1) { - if (sharedData_ && sharedData_[0] != '\0') { - std::string message(sharedData_, strnlen(sharedData_, 256)); + if (shmId_get != -1) { + if (sharedData_get && sharedData_get[0] != '\0') { + std::string message(sharedData_get, strnlen(sharedData_get, 256)); ins = message; // std::cout << "Received message: " << message << " ins " << ins.length() << std::endl; } @@ -303,9 +318,9 @@ class Concore{ while ((int)ins.length()==0){ this_thread::sleep_for(timespan); try{ - if(shmId_ != -1) { + if(shmId_get != -1) { std::cout << "in read while\n"; - std::string message(sharedData_, strnlen(sharedData_, 256)); + std::string message(sharedData_get, strnlen(sharedData_get, 256)); ins = message; retrycount++; } @@ -332,7 +347,7 @@ class Concore{ void write(int port, string name, vector val, int delta=0) { - if(communication_ == 1) + if(communication_oport == 1) { return write_SM(port, name, val, delta); } @@ -342,7 +357,7 @@ class Concore{ void write(int port, string name, string val, int delta=0) { - if(communication_ == 1) + if(communication_oport == 1) { return write_SM(port, name, val, delta); } @@ -398,14 +413,14 @@ class Concore{ try { std::ostringstream outfile; - if(shmId_ != -1){ + if(shmId_create != -1){ val.insert(val.begin(),simtime+delta); outfile<<'['; for(int i=0;i Date: Sat, 1 Jul 2023 23:57:00 +0530 Subject: [PATCH 4/5] implemented Shared memory based on initial positive integer of edge --- concore.hpp | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/concore.hpp b/concore.hpp index 3f8797f..7663332 100644 --- a/concore.hpp +++ b/concore.hpp @@ -50,8 +50,8 @@ class Concore{ oport = mapParser("concore.oport"); std::map::iterator it_iport = iport.begin(); std::map::iterator it_oport = oport.begin(); - int iport_number = generateNumberString(it_iport->first); - int oport_number = generateNumberString(it_oport->first); + int iport_number = ExtractNumeric(it_iport->first); + int oport_number = ExtractNumeric(it_oport->first); if(oport_number != -1) { @@ -76,18 +76,7 @@ class Concore{ shmctl(shmId_create, IPC_RMID, nullptr); } - std::map createAlphabetMap() { - std::map alphabetMap; - - for (char c = 'A'; c <= 'Z'; ++c) { - alphabetMap[c] = c - 'A' + 1; - } - - return alphabetMap; - } - - key_t generateNumberString(const std::string& str) { - std::map alphabetMap = createAlphabetMap(); + key_t ExtractNumeric(const std::string& str) { std::string numberString; // Find the number of leading digits in the input string @@ -95,7 +84,7 @@ class Concore{ std::string start_digit = ""; while (numDigits < str.length() && std::isdigit(str[numDigits])) { numberString += str[numDigits]; - ++numDigits; + ++numDigits; } if (numDigits == 0) @@ -103,11 +92,11 @@ class Concore{ return -1; } - // Concatenate the numbers for the first three alphabet characters after the digits - for (size_t i = numDigits; i < str.length() && i < numDigits + 3; ++i) { - char c = std::toupper(str[i]); - if (alphabetMap.count(c) > 0) { - numberString += std::to_string(alphabetMap[c]); + if (numDigits == 1) + { + if (std::stoi(numberString) <= 0) + { + return -1; } } From 2b204fbbf9677f902039b20cf9871fc0dc278a4f Mon Sep 17 00:00:00 2001 From: Shivang Vijay Date: Sun, 2 Jul 2023 00:39:27 +0530 Subject: [PATCH 5/5] Added comments in the concore.hpp file to help developer --- concore.hpp | 121 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 111 insertions(+), 10 deletions(-) diff --git a/concore.hpp b/concore.hpp index 7663332..02bb36a 100644 --- a/concore.hpp +++ b/concore.hpp @@ -20,6 +20,10 @@ using namespace std; +/** + * @class Concore + * @brief Class representing the Concore implementation in C++ + */ class Concore{ private: @@ -44,7 +48,11 @@ class Concore{ map iport; map oport; - //Constructor to put in iport and oport values in map + /** + * @brief Constructor for Concore class. + * Initializes the iport and oport maps by parsing the respective files. + * It also creates or attaches to the shared memory segment if required. + */ Concore(){ iport = mapParser("concore.iport"); oport = mapParser("concore.oport"); @@ -66,6 +74,10 @@ class Concore{ } } + /** + * @brief Destructor for Concore class. + * Detaches and removes the shared memory segment if shared memory created. + */ ~Concore() { // Detach the shared memory segment from the process @@ -76,6 +88,12 @@ class Concore{ shmctl(shmId_create, IPC_RMID, nullptr); } + /** + * @brief Extracts the numeric part from a string. + * @param str The input string. + * @return The numeric part of the string. + * Returns -1 if the string does not contain a numeric part. + */ key_t ExtractNumeric(const std::string& str) { std::string numberString; @@ -103,6 +121,10 @@ class Concore{ return std::stoi(numberString); } + /** + * @brief Creates a shared memory segment with the given key. + * @param key The key for the shared memory segment. + */ void createSharedMemory(key_t key) { shmId_create = shmget(key, 256, IPC_CREAT | 0666); @@ -118,6 +140,11 @@ class Concore{ } } + /** + * @brief Retrieves an existing shared memory segment with the given key. + * Waits until the shared memory segment is created by the writer process. + * @param key The key for the shared memory segment. + */ void getSharedMemory(key_t key) { while (true) { @@ -136,6 +163,11 @@ class Concore{ sharedData_get = static_cast(shmat(shmId_get, NULL, 0)); } + /** + * @brief Parses a file containing port and number mappings and returns a map of the values. + * @param filename The name of the file to parse. + * @return A map of port names and their corresponding numbers. + */ map mapParser(string filename){ map ans; @@ -180,7 +212,10 @@ class Concore{ return ans; } - //function to compare and determine whether file content has been changed + /** + * @brief function to compare and determine whether file content has been changed. + * @return true if the content has not changed, false otherwise. + */ bool unchanged(){ if(olds.compare(s)==0){ s = ""; @@ -192,6 +227,11 @@ class Concore{ } } + /** + * @brief Parses a string and extracts a vector of double values. + * @param f The input string to parse. + * @return A vector of double values extracted from the input string. + */ vector parser(string f){ vector temp; string value = ""; @@ -213,6 +253,13 @@ class Concore{ return temp; } + /** + * @brief deviate the read to either the SM (Shared Memory) or FM (File Method) communication protocol based on iport and oport. + * @param port The port number. + * @param name The name of the file. + * @param initstr The initial string + * @return + */ vector read(int port, string name, string initstr) { if(communication_iport == 1) @@ -223,7 +270,13 @@ class Concore{ return read_FM(port, name, initstr); } - //accepts the file name as string and returns a string of file content + /** + * @brief Reads data from a specified port and name using the FM (File Method) communication protocol. + * @param port The port number. + * @param name The name of the file. + * @param initstr The initial string. + * @return a string of file content + */ vector read_FM(int port, string name, string initstr){ chrono::milliseconds timespan((int)(1000*delay)); this_thread::sleep_for(timespan); @@ -279,7 +332,13 @@ class Concore{ } - //accepts the file name as string and returns a string of file content + /** + * @brief Reads data from the shared memory segment based on the specified port and name. + * @param port The port number. + * @param name The name of the file. + * @param initstr The initial string to use if the shared memory is not found. + * @return string of file content + */ vector read_SM(int port, string name, string initstr){ chrono::milliseconds timespan((int)(1000*delay)); this_thread::sleep_for(timespan); @@ -334,6 +393,13 @@ class Concore{ } + /** + * @brief deviate the write to either the SM (Shared Memory) or FM (File Method) communication protocol based on iport and oport. + * @param port The port number. + * @param name The name of the file. + * @param val The vector of double values to write. + * @param delta The delta value (default: 0). + */ void write(int port, string name, vector val, int delta=0) { if(communication_oport == 1) @@ -344,6 +410,14 @@ class Concore{ return write_FM(port, name, val, delta); } + + /** + * @brief deviate the write to either the SM (Shared Memory) or FM (File Method) communication protocol based on iport and oport. + * @param port The port number. + * @param name The name of the file. + * @param val The string to write. + * @param delta The delta value (default: 0). + */ void write(int port, string name, string val, int delta=0) { if(communication_oport == 1) @@ -354,7 +428,13 @@ class Concore{ return write_FM(port, name, val, delta); } - //write method, accepts a vector double and writes it to the file + /** + * @brief write method, accepts a vector double and writes it to the file + * @param port The port number. + * @param name The name of the file. + * @param val The string to write. + * @param delta The delta value (default: 0). + */ void write_FM(int port, string name, vector val, int delta=0){ try { @@ -378,7 +458,13 @@ class Concore{ } } - //write method, accepts a string and writes it to the file + /** + * @brief write method, accepts a string and writes it to the file + * @param port The port number. + * @param name The name of the file. + * @param val The string to write. + * @param delta The delta value (default: 0). + */ void write_FM(int port, string name, string val, int delta=0){ chrono::milliseconds timespan((int)(2000*delay)); this_thread::sleep_for(timespan); @@ -397,7 +483,13 @@ class Concore{ } } - //write method, accepts a vector double and writes it to the file + /** + * @brief Writes a vector of double values to the shared memory segment based on the specified port and name. + * @param port The port number. + * @param name The name of the file. + * @param val The vector of double values to write. + * @param delta The delta value (default: 0). + */ void write_SM(int port, string name, vector val, int delta=0){ try { @@ -421,7 +513,13 @@ class Concore{ } } - //write method, accepts a string and writes it to the file + /** + * @brief Writes a string to the shared memory segment based on the specified port and name. + * @param port The port number. + * @param name The name of the file. + * @param val The string to write. + * @param delta The delta value (default: 0). + */ void write_SM(int port, string name, string val, int delta=0){ chrono::milliseconds timespan((int)(2000*delay)); this_thread::sleep_for(timespan); @@ -436,7 +534,11 @@ class Concore{ } } - //Initialising + /** + * @brief Initializes the system with the given input values. + * @param f The input string containing the values. + * @return A vector of double values representing the initialized system state. + */ vector initval(string f){ //parsing vector val = parser(f); @@ -448,5 +550,4 @@ class Concore{ val.erase(val.begin()); return val; } - };