/** * \file ipc_send.h * \brief definition de classe * \author { * Sébastien Ambroziak * Paul Sauvage * } * \version 0.1 * \date 5 novembre 2020 * * Definitions de la classe IpcSender ainsi que ses méthodes. * Cette classe permet d'envoyer des structures ou des liste de structure par ipc * * La classe IpcSender utilise une template à 2 paramètres, T et N * le paramètre T correspond au type de donnée que le sender doit pouvoir envoyer * le paramètre N correspond au nombre d'élément du tableau d'élément de type T à envoyer * si N = 0 la fonction send() prend en paramètre et envoi une structure de type T * si N > 0 la fonction send() prend en paramètre et envoi un tableau de N éléments de type T * * Le constructeur utilise 2 paramètres: * Une chaîne de caractère contenant le nom du fichier ipc vers lequel écrire les données * Un entier correspond au numéro de canal Ipc * */ #ifndef SHM_SEND #define SHM_SEND #include "ipc_base.h" #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace ipc::type; class ShmSenderBase { public: ShmSenderBase(size_t msg_size, const char* ipc_name, int proj_id=65) { cout << "Creating ShmSender" << 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); //create 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; _semaphore.sem_num=0; //init semaphore _semaphore.sem_op=1; semop(_semid,&_semaphore,1); /*struct shmid_ds buf; shmctl(_shmid, IPC_STAT,&buf); buf.shm_perm.mode = (S_IRWXU|S_IRWXG|S_IRWXO); shmctl(_shmid, IPC_SET,&buf);*/ } ~ShmSenderBase() { 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 ShmSender : ShmSenderBase { public: ShmSender(const char* ipc_name, int proj_id=65, bool auto_refresh = true): ShmSenderBase(sizeof(ipc_message), ipc_name, proj_id), _auto_refresh(auto_refresh) {} ~ShmSender() = default; void send(){ if(_auto_refresh) refreshTime(); _semaphore.sem_num=0; _semaphore.sem_op=-1; //getMutex semop(_semid,&_semaphore,1); memcpy(_shm_ptr, &_message, sizeof(ipc_message)); //write message _semaphore.sem_num=0; _semaphore.sem_op=1; //release mutex semop(_semid,&_semaphore,1); } void send(T value) { _message.data.value = value; send(); } timestamp getTimestamp(){ return _message.data.stamp; } timestamp refreshTime(){ _message.time_now(); return _message.data.stamp; } T getValue(){return _message.data.value;} void setValue(T value){_message.data.value = value;} void setTimestamp(timestamp stamp){_message.data.stamp = stamp;} void setTimestamp(int32_t sec, uint32_t nanosec){ _message.data.stamp.sec = sec; _message.data.stamp.nanosec = nanosec; } protected: bool _auto_refresh; ipc_message _message; ipc_message *_shm_ptr = (ipc_message*) shmat(_shmid,(void*)0,0); // shmat to attach to shared memory }; template class ShmSenderTab : ShmSenderBase { public: ShmSenderTab(size_t N, const char* ipc_name, int proj_id=65, bool auto_refresh = true): ShmSenderBase(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-1)); _message->msg_type = 1; } ~ShmSenderTab() = default; void send(T* values){ memcpy(_message->data.values, values, sizeof(T)*_N); send(); } void send(){ if(_auto_refresh) refreshTime(); _semaphore.sem_num=0; _semaphore.sem_op=-1; //getMutex semop(_semid,&_semaphore,1); memcpy(_shm_ptr, _message, sizeof(ipc_tab) + sizeof(T)*_N); //write message _semaphore.sem_num=0; _semaphore.sem_op=1; //release mutex semop(_semid,&_semaphore,1); } void setTimestamp(timestamp stamp){_message->data.stamp = stamp;} void setTimestamp(int32_t sec, uint32_t nanosec){ _message->data.stamp.sec = sec; _message->data.stamp.nanosec = nanosec; } timestamp getTimestamp(){ return _message->data.stamp; } timestamp refreshTime(){ _message->time_now(); return _message->data.stamp; } void setValue(T value, size_t index){ if(index < _N){ _message->data.values[index] = value; } } void setAll(T value) { for (size_t i = 0; i < _N; i++) { _message->data.values[i] = value; } } void setValues(T* values){ memcpy(_message->data.values, values, sizeof(T)*_N); } size_t getN() const {return _N;} protected: size_t _N; bool _auto_refresh; ipc_tab* _message; ipc_tab *_shm_ptr = (ipc_tab*) shmat(_shmid,(void*)0,0); // shmat to attach to shared memory }; #endif