nmpp
ringremote.h
1#ifndef RINGREMOTE_INCLUDED
2#define RINGREMOTE_INCLUDED
3#include <string.h>
4#include <time.h>
5
6#define MIN(a,b) ((a) > (b) ? (b) : (a))
7
8#define RING_BUFFER_DECLARED 0xDEC1A8ED
9#define RING_BUFFER_ALLOCATED 0xA10CA7ED
10#define RING_BUFFER_MEM_ERROR 0xDEADF00D
11#define RING_BUFFER_ERROR 0xBEDABEDA
12#define RING_BUFFER_OK 0x0
13
14#define EXIT_ON_TIMEOUT 1
15#define EXIT_ON_COMPLETED 0
16#define EXIT_ON_FULL_BUFFER 2
17#define EXIT_ON_EMPTY_BUFFER 2
18
19//void Sleep(int msec);
20
21typedef void *(*t_memcpy)(void *to, int toIndex, const void *from, int fromIndex, size_t size) ;
22typedef void *(*t_bytecpy)(void *to, int toIndex, void const *from, int fromIndex, size_t size) ;
23
24#ifdef __NM__
25 #define bytesizeof(T) (sizeof(T)<<2)
26#else
27 #define bytesizeof(T) sizeof(T)
28#endif
29
30#if defined(_WIN32) && !defined(__GNUC__)
31 #include "crtdbg.h"
32#else
33 #define _ASSERTE(val)
34#endif
35
36
37
38
39template <class T> class C_RingBufferRemote{
40private:
41
42public:
43 //size_t sizeof_size_t;
44 //size_t sizeof_T;
45 size_t data_addr;
46 size_t head_addr;
47 size_t tail_addr;
48
49 size_t size;
50 size_t head;
51 size_t tail;
52 size_t id;
53 bool isConnected;
54
55
56 t_bytecpy push_memcpy;
57 t_bytecpy pop_memcpy;
58
59 // ------------- dma --------------
60 t_memcpy dma_init;
61 size_t(*dma_check)();
62 T* dma_ptr;
63 size_t dma_left;
64 size_t dma_size;
65 //----------------------------------
66 unsigned timeout;
67 unsigned time2sleep;
68 int pad[16-3-5*sizeof(t_bytecpy)/sizeof(int)];
69
70
71
73 isConnected=false;
74 }
75
76 C_RingBufferRemote(size_t ringbuffer_addr, t_bytecpy push_memcopy, t_bytecpy pop_memcopy){
77 Init( ringbuffer_addr, push_memcopy, pop_memcopy);
78 }
79
80 size_t GetHead(){
81 pop_memcpy(&head,0,(const void*)head_addr,0,bytesizeof(size_t));
82 return head;
83 }
84 size_t GetTail(){
85 pop_memcpy(&tail,0,(const void*)tail_addr,0,bytesizeof(size_t));
86 return tail;
87 }
88 void SetHead(){
89 push_memcpy((void*)head_addr,0,&head,0, bytesizeof(size_t));
90 }
91 void SetTail(){
92 push_memcpy((void*)tail_addr,0,&tail,0,bytesizeof(size_t));
93 }
94
95 bool Init(size_t ringbuffer_addr, t_bytecpy push_memcopy, t_bytecpy pop_memcopy){
96 //sizeof_size_t=0;
97 //sizeof_T=0;
98 data_addr=0xCCCCCCCC;
99 head_addr=0xCCCCCCCC;
100 tail_addr=0xCCCCCCCC;
101 size=0xCCCCCCCC;
102 head=0xCCCCCCCC;
103 tail=0xCCCCCCCC;
104 isConnected=false;
105
106 dma_init=0;
107 dma_check=0;
108 dma_ptr =0;
109 dma_left=0;
110 dma_size=0;
111 time2sleep=10;
112 timeout=100;
113
114
115 push_memcpy=push_memcopy;
116 pop_memcpy =pop_memcopy;
117
118 pop_memcpy(&data_addr,0,(void*)ringbuffer_addr,+0*bytesizeof(size_t),bytesizeof(size_t));
119 pop_memcpy(&size, 0,(void*)ringbuffer_addr,+1*bytesizeof(size_t),bytesizeof(size_t));
120 pop_memcpy(&head_addr,0,(void*)ringbuffer_addr,+4*bytesizeof(size_t),bytesizeof(size_t));
121 pop_memcpy(&tail_addr,0,(void*)ringbuffer_addr,+5*bytesizeof(size_t),bytesizeof(size_t));
122 pop_memcpy(&id, 0,(void*)ringbuffer_addr,+6*bytesizeof(size_t),bytesizeof(size_t));
123
124 if ((size&(size-1))!=0) // check that size is power of two
125 return false;
126
127
128 if (id!=0x600DB00F)
129 return false;
130
131 id = 0xB00F600D;
132 push_memcpy((void*)ringbuffer_addr,+6*bytesizeof(size_t),&id,0,bytesizeof(size_t));
133 id =0;
134 pop_memcpy(&id, 0,(void*)ringbuffer_addr,+6*bytesizeof(size_t),bytesizeof(size_t));
135 if (id!=0xB00F600D) // no access to remote rinbuffer.id
136 return false;
137
138
139 GetHead();
140 GetTail();
141 if (head==0xCCCCCCCC || tail==0xCCCCCCCC)
142 return false;
143
144
145 isConnected = true;
146 return true;
147 }
148
149 __INLINE__ bool IsFull(){
150 GetHead();
151 GetTail();
152 return (head-tail==size);
153 }
154 __INLINE__ bool IsEmpty(){
155 GetHead();
156 GetTail();
157 return (head==tail);
158 }
159 __INLINE__ size_t GetWriteAvail(){
160 GetHead();
161 GetTail();
162 return (size-(head-tail));
163 }
164 __INLINE__ size_t GetReadAvail(){
165 GetHead();
166 GetTail();
167 return (head-tail);
168 }
169
170 /*
171 T* Head(){
172 if (GetWriteAvail()==0)
173 return 0;
174 size_t headPointer=head&(size-1);
175 T* pElement=(T*)(data_addr+headPointer*bytesizeof(T));
176 return pElement;
177 }
178 T* Tail(){
179 if (GetReadAvail()==0)
180 return 0;
181 size_t tailPointer=tail&(size-1);
182 T* pElement=(T*)(data_addr+tailPointer*sizeof_T);
183 return pElement;
184 }*/
185
186 bool Push(int numElements){
187 GetHead();
188 GetTail();
189 size_t h=head+numElements;
190 if (h>tail+size)
191 return RING_BUFFER_ERROR;
192 head=h;
193 return RING_BUFFER_OK;
194 }
195
196 bool Pop(int numElements){
197 GetHead();
198 GetTail();
199 size_t t=tail+numElements;
200 if (t>head)
201 return RING_BUFFER_ERROR;
202 tail=t;
203 return RING_BUFFER_OK;
204 }
205
206
207 size_t Push(T* pSrcElements, size_t numElements, int ExitMode= EXIT_ON_COMPLETED)
208 {
209 GetHead();
210 size_t initHead=head;
211 size_t count;
212 size_t diff;
213 clock_t t0=clock();
214 size_t posSrc=0;
215 while (numElements){
216 GetHead();
217 GetTail();
218 _ASSERTE(head>=tail);
219 size_t posHead=head&(size-1);
220 size_t posTail=tail&(size-1);
221 if (posTail<posHead || head==tail)
222 diff=size-posHead;
223 else if (posHead<posTail)
224 diff=posTail-posHead;
225 else if (ExitMode&EXIT_ON_FULL_BUFFER) // buffer is full
226 return (head-initHead);
227 else if (ExitMode&EXIT_ON_TIMEOUT){
228 if ((clock()-t0)>timeout*(CLOCKS_PER_SEC/1000))
229 return (head-initHead);
230 Sleep(time2sleep);
231 continue;
232 } else {
233 Sleep(time2sleep);
234 continue;
235 }
236
237 count=MIN(numElements,diff);
238 if (push_memcpy((void*)data_addr,posHead*bytesizeof(T),pSrcElements,posSrc*bytesizeof(T),count*bytesizeof(T))){
239 head+=count;
240 posSrc+=count;
241 numElements -=count;
242 SetHead();
243 GetHead();
244 }
245
246 }
247 return (head-initHead);
248 }
249
250
251 /*
252 void PushRequest(T* pSrcElements, size_t numElements)
253 {
254 GetHead();
255 GetTail();
256 size_t posHead;
257 size_t posTail;
258 size_t diff=0;
259 while(diff==0){
260 posHead=head&(size-1);
261 posTail=tail&(size-1);
262 if (posTail<posHead || head==tail)
263 diff=size-posHead;
264 else if (posHead<posTail)
265 diff=posTail-posHead;
266 else { // buffer is full
267 Sleep(time2sleep);
268 continue;
269 }
270 }
271 dma_ptr =pSrcElements;
272 dma_left =numElements;
273 dma_size =MIN(dma_left,diff);
274 dma_init(data_addr+posHead*sizeof_T,pSrcElements,dma_size*sizeof_T);
275 }
276
277 bool isPushCompleted()
278 {
279 SetHead();
280 if (dma_left==0)
281 return true;
282 if (dma_check())
283 return false;
284
285 head +=dma_size;
286 dma_ptr +=dma_size;
287 dma_left -=dma_size;
288 SetHead();
289 if (dma_left){
290 PushRequest(dma_ptr,dma_left);
291 return false;
292 }
293 return true;
294
295 }
296
297 */
298
299
300
301
302 size_t Pop(T* pDstElements, size_t numElements, int ExitMode= EXIT_ON_COMPLETED)
303 {
304 GetTail();
305 size_t initTail=tail;
306 size_t count;
307 size_t diff;
308 clock_t t0=clock();
309 size_t posDst=0;
310 while (numElements){
311 //GetTail();
312 GetHead();
313 size_t posHead=head&(size-1);
314 size_t posTail=tail&(size-1);
315 if (posTail<posHead )
316 diff=posHead-posTail;
317 else if (posHead<=posTail && head!=tail)
318 diff=size-posTail;
319 else if (ExitMode&EXIT_ON_EMPTY_BUFFER) // buffer is empty
320 return (tail-initTail);
321 else if (ExitMode&EXIT_ON_TIMEOUT){
322 if ((clock()-t0)>timeout)
323 return (tail-initTail);
324 Sleep(time2sleep);
325 continue;
326 } else {
327 Sleep(time2sleep);
328 continue;
329 }
330
331 count=MIN(numElements,diff);
332 pop_memcpy(pDstElements,posDst*bytesizeof(T),(const void*)(data_addr),posTail*bytesizeof(T),count*bytesizeof(T));
333 tail+=count;
334 posDst+=count;
335 numElements -=count;
336 SetTail();
337 }
338 return (tail-initTail);
339 }
340
341 size_t View(T* pDstElements, size_t numElements, int ExitMode= EXIT_ON_COMPLETED)
342 {
343 GetTail();
344 size_t initTail=tail;
345 size_t count;
346 size_t diff;
347 clock_t t0=clock();
348 size_t posDst=0;
349 while (numElements){
350 //GetTail();
351 GetHead();
352 size_t posHead=head&(size-1);
353 size_t posTail=tail&(size-1);
354 if (posTail<posHead )
355 diff=posHead-posTail;
356 else if (posHead<=posTail && head!=tail)
357 diff=size-posTail;
358 else if (ExitMode&EXIT_ON_EMPTY_BUFFER){ // buffer is empty
359 size_t ret=tail-initTail;
360 tail=initTail;
361 return ret;
362 }
363 else if (ExitMode&EXIT_ON_TIMEOUT){
364 if ((clock()-t0)>timeout){
365 size_t ret=tail-initTail;
366 tail=initTail;
367 return ret;
368 }
369 Sleep(time2sleep);
370 continue;
371 } else {
372 Sleep(time2sleep);
373 continue;
374 }
375
376 count=MIN(numElements,diff);
377 pop_memcpy(pDstElements,posDst*bytesizeof(T),(const void*)data_addr,posTail*bytesizeof(T),count*bytesizeof(T));
378 tail+=count;
379 posDst+=count;
380 numElements -=count;
381 //SetTail();
382 }
383 size_t ret=tail-initTail;
384 tail=initTail;
385 return ret;
386 }
387
388
389
390};
391
392
393#endif
Definition: ringremote.h:39
size_t head
сколько элементов ОТ НАЧАЛА ПОТОКА код MASTER уже записал в буфер входных данных [заполняется MASTER]
Definition: ringremote.h:50
size_t tail
сколько элементов ОТ НАЧАЛА ПОТОКА код SLAVE уже прочитал (обработал) [заполняется SLAVE]
Definition: ringremote.h:51
size_t data_addr
физический адрес кольцевого буфера входных данных
Definition: ringremote.h:45
size_t head_addr
сколько элементов ОТ НАЧАЛА ПОТОКА код MASTER уже записал в буфер входных данных [заполняется MASTER]
Definition: ringremote.h:46
size_t id
сколько элементов ОТ НАЧАЛА ПОТОКА код SLAVE уже прочитал (обработал) [заполняется SLAVE]
Definition: ringremote.h:52
size_t size
размер кольцевого буфера входных данных (в элементах; гарантируется что это степень двойки)
Definition: ringremote.h:49
int pad[16-3-5 *sizeof(t_bytecpy)/sizeof(int)]
резервные поля
Definition: ringremote.h:68
size_t tail_addr
сколько элементов ОТ НАЧАЛА ПОТОКА код SLAVE уже прочитал (обработал) [заполняется SLAVE]
Definition: ringremote.h:47