source: flair-src/trunk/lib/FlairIpc/src/unexported/shm_receive.h @ 397

Last change on this file since 397 was 397, checked in by Sanahuja Guillaume, 7 months ago

add ipc lib

  • Property svn:eol-style set to native
File size: 5.4 KB
Line 
1/**
2 * \file ipc_receive.h
3 * \brief definition de classe
4 * \author {
5 *                      Sébastien Ambroziak
6 *                      Paul Sauvage
7 *                      }
8 * \version 0.1
9 * \date 5 novembre 2020
10 *
11 * Definitions de la classe IpcReceiver ainsi que ses méthodes.
12 * Cette classe permet de recevoir des structures ou des liste de structure par ipc
13 *
14 * La classe IpcReceiver utilise une template à 2 paramètres, T et N
15 *      le paramètre T correspond au type de donnée que le receiver doit recevoir
16 *      le paramètre N correspond au nombre d'élément du tableau d'élément de type T à recevoir
17 *              si N = 0 la fonction receive() retourne directement un objet de type T
18 *              si N > 0 la fonction receive() retourne un pointeur de type T et donc un tableau d'élément T de N éléments
19 *
20 * Le constructeur utilise 2 paramètres:
21 *  Une chaîne de caractère contenant le nom du fichier ipc vers lequel lire les données
22 *  Un entier correspond au numéro de canal Ipc
23 *
24 */
25
26
27
28#ifndef SHM_RECEIVE
29#define SHM_RECEIVE
30
31#include "ipc_base.h"
32
33#include <functional>
34#include <memory>
35#include <iostream>
36#include <stdio.h>
37#include <type_traits>
38#include <cstring>
39
40#include <sys/ipc.h>
41#include <sys/msg.h>
42#include <sys/shm.h>
43#include <sys/stat.h>
44#include <sys/types.h>
45#include <sys/sem.h>
46#include <sys/time.h>
47#include <string>
48#include <errno.h>
49
50using namespace std;
51using namespace ipc::type;
52
53class ShmReceiverBase {
54        public:
55                ShmReceiverBase(size_t msg_size, const char* ipc_name, int proj_id=65){
56                        cout << "Creating ShmReceiver" << endl;
57                        system("mkdir -p /tmp/shmem");
58                        system("chmod 777 /tmp/shmem");
59                        string pathname = string("/tmp/shmem/") + string(ipc_name);
60                        string command = string("> ") + pathname;
61                        system(command.c_str());
62                        command = string("chmod 666 ") + pathname;
63                        system(command.c_str());
64
65                        key_t ipc_key = ftok(pathname.c_str(), proj_id); //crete unique key
66                        cout << "clé ipc" << ipc_key << endl;
67
68                        _shmid = shmget(ipc_key, msg_size, 0666|IPC_CREAT); // shmget returns an identifier in shmid
69                        cout << "Shm Id : " << _shmid << endl;
70
71                        _semid=semget(ipc_key,1,IPC_CREAT|0666);
72                        cout << "Sem Id : " << _semid << endl;
73
74                        /*struct shmid_ds buf;
75                        shmctl(_shmid, IPC_STAT,&buf);
76                        buf.shm_perm.mode = (S_IRWXU|S_IRWXG|S_IRWXO);
77                        shmctl(_shmid, IPC_SET,&buf);*/
78                }
79
80                ~ShmReceiverBase(){
81                        shmctl(_shmid, IPC_RMID, NULL); // destroy the shared memory
82                        semctl(_semid, 0, IPC_RMID); // destroy semaphore
83                } 
84
85        protected:
86                int _shmid;
87                int _semid;
88                struct sembuf _semaphore; 
89};
90
91template <typename T>
92class ShmReceiver : ShmReceiverBase {
93        public:
94                ShmReceiver(const char* ipc_name, int proj_id=65, bool auto_refresh = false): ShmReceiverBase(sizeof(ipc_message<T>), ipc_name, proj_id), _auto_refresh(auto_refresh) {}
95                ~ShmReceiver() = default;
96
97                int receive(){
98                        int return_value = 0;
99                        _semaphore.sem_num=0;
100                        _semaphore.sem_op=-1; //getMutex
101                        semop(_semid,&_semaphore,1);
102
103                        if ((tmp.sec == _shm_ptr->data.stamp.sec) && (tmp.nanosec == _shm_ptr->data.stamp.nanosec)){
104                                return_value = -1; //Donnée obsolète
105                               
106                                if(_auto_refresh == true){
107                                        refreshTime();
108                                }
109                        }
110                        else{
111                                tmp.sec = _shm_ptr->data.stamp.sec;
112                                tmp.nanosec = _shm_ptr->data.stamp.nanosec;
113                                memcpy(&_message, _shm_ptr, sizeof(ipc_message<T>)); //write message
114                        }
115                       
116                        _semaphore.sem_num=0;
117                        _semaphore.sem_op=1; //release mutex
118                        semop(_semid,&_semaphore,1);
119
120                        return return_value;
121                }
122
123                timestamp getTimestamp() const {
124                        return _message.data.stamp;
125                }
126
127                T getValue() const {return _message.data.value;}
128
129                timestamp refreshTime(){
130                        _message.time_now();
131                        return _message.data.stamp;
132                }
133
134
135        protected:
136                timestamp tmp;
137                bool _auto_refresh;
138                ipc_message<T> *_shm_ptr = (ipc_message<T>*) shmat(_shmid,(void*)0, SHM_RDONLY); // shmat to attach to shared memory
139                ipc_message<T> _message;
140                bool _blocking;
141};
142
143template <typename T>
144class ShmReceiverTab : ShmReceiverBase {
145        public:
146                ShmReceiverTab(size_t N, const char* ipc_name, int proj_id=65, bool auto_refresh = false): ShmReceiverBase(sizeof(ipc_tab<T>) + sizeof(T)*(N-1), ipc_name, proj_id), _N(N), _auto_refresh(auto_refresh) {
147                        _message = (ipc_tab<T>*) malloc(sizeof(ipc_tab<T>) + sizeof(T)*N);
148                }
149
150                ~ShmReceiverTab() = default;
151
152                int receive(){
153                       
154                        int return_value = 0;
155                        _semaphore.sem_num=0;
156                        _semaphore.sem_op=-1; //getMutex
157                        semop(_semid,&_semaphore,1);
158
159                        if ((tmp.sec == _shm_ptr->data.stamp.sec) && (tmp.nanosec == _shm_ptr->data.stamp.nanosec)){
160                                return_value = -1; //Donnée obsolète
161                                if(_auto_refresh == true)
162                                        refreshTime();
163                        }
164                        else{
165                                tmp.sec = _shm_ptr->data.stamp.sec;
166                                tmp.nanosec = _shm_ptr->data.stamp.nanosec;
167                                memcpy(_message, _shm_ptr, sizeof(ipc_tab<T>) + sizeof(T)*_N); //write message
168                        }
169                       
170                        _semaphore.sem_num=0;
171                        _semaphore.sem_op=1; //release mutex
172                        semop(_semid,&_semaphore,1);
173
174                        return return_value;
175                }
176               
177                T getValue(size_t index) const {
178                        return _message->data.values[index];
179                }
180
181                const T* getValues() const {
182                        return _message->data.values;
183                }
184
185                timestamp getTimestamp() const {
186                        return _message->data.stamp;
187                }
188
189                size_t getN() const {return _N;}
190
191                timestamp refreshTime(){
192                        _message->time_now();
193                        return _message->data.stamp;
194                }
195
196                void setAll(T value) {
197                        for (size_t i = 0; i < _N; i++)
198                        {
199                                _message->data.values[i] = value;
200                        }
201                }
202
203        protected:
204                timestamp tmp;
205                size_t _N;
206                bool _auto_refresh;
207                ipc_tab<T> *_message;
208                ipc_tab<T> *_shm_ptr = (ipc_tab<T>*) shmat(_shmid,(void*)0,SHM_RDONLY); // shmat to attach to shared memory
209               
210};
211
212#endif
Note: See TracBrowser for help on using the repository browser.