/** * \file ipc_receive.h * \brief definition de classe * \author { * Sébastien Ambroziak * Paul Sauvage * } * \version 0.1 * \date 5 novembre 2020 * * Definitions de la classe IpcReceiver ainsi que ses méthodes. * Cette classe permet de recevoir des structures ou des liste de structure par ipc * * La classe IpcReceiver utilise une template à 2 paramètres, T et N * le paramètre T correspond au type de donnée que le receiver doit recevoir * le paramètre N correspond au nombre d'élément du tableau d'élément de type T à recevoir * si N = 0 la fonction receive() retourne directement un objet de type T * si N > 0 la fonction receive() retourne un pointeur de type T et donc un tableau d'élément T de N éléments * * Le constructeur utilise 2 paramètres: * Une chaîne de caractère contenant le nom du fichier ipc vers lequel lire les données * Un entier correspond au numéro de canal Ipc * */ #ifndef SHM_RECEIVE #define SHM_RECEIVE #include "ipc_base.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace ipc::type; class ShmReceiverBase { public: ShmReceiverBase(size_t msg_size, const char* ipc_name, int proj_id=65){ cout << "Creating ShmReceiver" << endl; system("mkdir -p /tmp/shmem"); system("chmod 777 /tmp/shmem"); string pathname = string("/tmp/shmem/") + string(ipc_name); string command = string("> ") + pathname; system(command.c_str()); command = string("chmod 666 ") + pathname; system(command.c_str()); key_t ipc_key = ftok(pathname.c_str(), proj_id); //crete unique key cout << "clé ipc" << ipc_key << endl; _shmid = shmget(ipc_key, msg_size, 0666|IPC_CREAT); // shmget returns an identifier in shmid cout << "Shm Id : " << _shmid << endl; _semid=semget(ipc_key,1,IPC_CREAT|0666); cout << "Sem Id : " << _semid << endl; /*struct shmid_ds buf; shmctl(_shmid, IPC_STAT,&buf); buf.shm_perm.mode = (S_IRWXU|S_IRWXG|S_IRWXO); shmctl(_shmid, IPC_SET,&buf);*/ } ~ShmReceiverBase(){ shmctl(_shmid, IPC_RMID, NULL); // destroy the shared memory semctl(_semid, 0, IPC_RMID); // destroy semaphore } protected: int _shmid; int _semid; struct sembuf _semaphore; }; template class ShmReceiver : ShmReceiverBase { public: ShmReceiver(const char* ipc_name, int proj_id=65, bool auto_refresh = false): ShmReceiverBase(sizeof(ipc_message), ipc_name, proj_id), _auto_refresh(auto_refresh) {} ~ShmReceiver() = default; int receive(){ int return_value = 0; _semaphore.sem_num=0; _semaphore.sem_op=-1; //getMutex semop(_semid,&_semaphore,1); if ((tmp.sec == _shm_ptr->data.stamp.sec) && (tmp.nanosec == _shm_ptr->data.stamp.nanosec)){ return_value = -1; //Donnée obsolète if(_auto_refresh == true){ refreshTime(); } } else{ tmp.sec = _shm_ptr->data.stamp.sec; tmp.nanosec = _shm_ptr->data.stamp.nanosec; memcpy(&_message, _shm_ptr, sizeof(ipc_message)); //write message } _semaphore.sem_num=0; _semaphore.sem_op=1; //release mutex semop(_semid,&_semaphore,1); return return_value; } timestamp getTimestamp() const { return _message.data.stamp; } T getValue() const {return _message.data.value;} timestamp refreshTime(){ _message.time_now(); return _message.data.stamp; } protected: timestamp tmp; bool _auto_refresh; ipc_message *_shm_ptr = (ipc_message*) shmat(_shmid,(void*)0, SHM_RDONLY); // shmat to attach to shared memory ipc_message _message; bool _blocking; }; template class ShmReceiverTab : ShmReceiverBase { public: ShmReceiverTab(size_t N, const char* ipc_name, int proj_id=65, bool auto_refresh = false): ShmReceiverBase(sizeof(ipc_tab) + sizeof(T)*(N-1), ipc_name, proj_id), _N(N), _auto_refresh(auto_refresh) { _message = (ipc_tab*) malloc(sizeof(ipc_tab) + sizeof(T)*N); } ~ShmReceiverTab() = default; int receive(){ int return_value = 0; _semaphore.sem_num=0; _semaphore.sem_op=-1; //getMutex semop(_semid,&_semaphore,1); if ((tmp.sec == _shm_ptr->data.stamp.sec) && (tmp.nanosec == _shm_ptr->data.stamp.nanosec)){ return_value = -1; //Donnée obsolète if(_auto_refresh == true) refreshTime(); } else{ tmp.sec = _shm_ptr->data.stamp.sec; tmp.nanosec = _shm_ptr->data.stamp.nanosec; memcpy(_message, _shm_ptr, sizeof(ipc_tab) + sizeof(T)*_N); //write message } _semaphore.sem_num=0; _semaphore.sem_op=1; //release mutex semop(_semid,&_semaphore,1); return return_value; } T getValue(size_t index) const { return _message->data.values[index]; } const T* getValues() const { return _message->data.values; } timestamp getTimestamp() const { return _message->data.stamp; } size_t getN() const {return _N;} timestamp refreshTime(){ _message->time_now(); return _message->data.stamp; } void setAll(T value) { for (size_t i = 0; i < _N; i++) { _message->data.values[i] = value; } } protected: timestamp tmp; size_t _N; bool _auto_refresh; ipc_tab *_message; ipc_tab *_shm_ptr = (ipc_tab*) shmat(_shmid,(void*)0,SHM_RDONLY); // shmat to attach to shared memory }; #endif