OLD | NEW |
| (Empty) |
1 /***************************************************************************** | |
2 Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. | |
3 All rights reserved. | |
4 | |
5 Redistribution and use in source and binary forms, with or without | |
6 modification, are permitted provided that the following conditions are | |
7 met: | |
8 | |
9 * Redistributions of source code must retain the above | |
10 copyright notice, this list of conditions and the | |
11 following disclaimer. | |
12 | |
13 * Redistributions in binary form must reproduce the | |
14 above copyright notice, this list of conditions | |
15 and the following disclaimer in the documentation | |
16 and/or other materials provided with the distribution. | |
17 | |
18 * Neither the name of the University of Illinois | |
19 nor the names of its contributors may be used to | |
20 endorse or promote products derived from this | |
21 software without specific prior written permission. | |
22 | |
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | |
24 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | |
25 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
26 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | |
27 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
28 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
29 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
30 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
31 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
32 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
33 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
34 *****************************************************************************/ | |
35 | |
36 /***************************************************************************** | |
37 written by | |
38 Yunhong Gu, last updated 01/22/2011 | |
39 *****************************************************************************/ | |
40 | |
41 #include "list.h" | |
42 | |
43 CSndLossList::CSndLossList(const int& size): | |
44 m_piData1(NULL), | |
45 m_piData2(NULL), | |
46 m_piNext(NULL), | |
47 m_iHead(-1), | |
48 m_iLength(0), | |
49 m_iSize(size), | |
50 m_iLastInsertPos(-1), | |
51 m_ListLock() | |
52 { | |
53 m_piData1 = new int32_t [m_iSize]; | |
54 m_piData2 = new int32_t [m_iSize]; | |
55 m_piNext = new int [m_iSize]; | |
56 | |
57 // -1 means there is no data in the node | |
58 for (int i = 0; i < size; ++ i) | |
59 { | |
60 m_piData1[i] = -1; | |
61 m_piData2[i] = -1; | |
62 } | |
63 | |
64 // sender list needs mutex protection | |
65 #ifndef WIN32 | |
66 pthread_mutex_init(&m_ListLock, 0); | |
67 #else | |
68 m_ListLock = CreateMutex(NULL, false, NULL); | |
69 #endif | |
70 } | |
71 | |
72 CSndLossList::~CSndLossList() | |
73 { | |
74 delete [] m_piData1; | |
75 delete [] m_piData2; | |
76 delete [] m_piNext; | |
77 | |
78 #ifndef WIN32 | |
79 pthread_mutex_destroy(&m_ListLock); | |
80 #else | |
81 CloseHandle(m_ListLock); | |
82 #endif | |
83 } | |
84 | |
85 int CSndLossList::insert(const int32_t& seqno1, const int32_t& seqno2) | |
86 { | |
87 CGuard listguard(m_ListLock); | |
88 | |
89 if (0 == m_iLength) | |
90 { | |
91 // insert data into an empty list | |
92 | |
93 m_iHead = 0; | |
94 m_piData1[m_iHead] = seqno1; | |
95 if (seqno2 != seqno1) | |
96 m_piData2[m_iHead] = seqno2; | |
97 | |
98 m_piNext[m_iHead] = -1; | |
99 m_iLastInsertPos = m_iHead; | |
100 | |
101 m_iLength += CSeqNo::seqlen(seqno1, seqno2); | |
102 | |
103 return m_iLength; | |
104 } | |
105 | |
106 // otherwise find the position where the data can be inserted | |
107 int origlen = m_iLength; | |
108 int offset = CSeqNo::seqoff(m_piData1[m_iHead], seqno1); | |
109 int loc = (m_iHead + offset + m_iSize) % m_iSize; | |
110 | |
111 if (offset < 0) | |
112 { | |
113 // Insert data prior to the head pointer | |
114 | |
115 m_piData1[loc] = seqno1; | |
116 if (seqno2 != seqno1) | |
117 m_piData2[loc] = seqno2; | |
118 | |
119 // new node becomes head | |
120 m_piNext[loc] = m_iHead; | |
121 m_iHead = loc; | |
122 m_iLastInsertPos = loc; | |
123 | |
124 m_iLength += CSeqNo::seqlen(seqno1, seqno2); | |
125 } | |
126 else if (offset > 0) | |
127 { | |
128 if (seqno1 == m_piData1[loc]) | |
129 { | |
130 m_iLastInsertPos = loc; | |
131 | |
132 // first seqno is equivlent, compare the second | |
133 if (-1 == m_piData2[loc]) | |
134 { | |
135 if (seqno2 != seqno1) | |
136 { | |
137 m_iLength += CSeqNo::seqlen(seqno1, seqno2) - 1; | |
138 m_piData2[loc] = seqno2; | |
139 } | |
140 } | |
141 else if (CSeqNo::seqcmp(seqno2, m_piData2[loc]) > 0) | |
142 { | |
143 // new seq pair is longer than old pair, e.g., insert [3, 7] to [3,
5], becomes [3, 7] | |
144 m_iLength += CSeqNo::seqlen(m_piData2[loc], seqno2) - 1; | |
145 m_piData2[loc] = seqno2; | |
146 } | |
147 else | |
148 // Do nothing if it is already there | |
149 return 0; | |
150 } | |
151 else | |
152 { | |
153 // searching the prior node | |
154 int i; | |
155 if ((-1 != m_iLastInsertPos) && (CSeqNo::seqcmp(m_piData1[m_iLastInsert
Pos], seqno1) < 0)) | |
156 i = m_iLastInsertPos; | |
157 else | |
158 i = m_iHead; | |
159 | |
160 while ((-1 != m_piNext[i]) && (CSeqNo::seqcmp(m_piData1[m_piNext[i]], s
eqno1) < 0)) | |
161 i = m_piNext[i]; | |
162 | |
163 if ((-1 == m_piData2[i]) || (CSeqNo::seqcmp(m_piData2[i], seqno1) < 0)) | |
164 { | |
165 m_iLastInsertPos = loc; | |
166 | |
167 // no overlap, create new node | |
168 m_piData1[loc] = seqno1; | |
169 if (seqno2 != seqno1) | |
170 m_piData2[loc] = seqno2; | |
171 | |
172 m_piNext[loc] = m_piNext[i]; | |
173 m_piNext[i] = loc; | |
174 | |
175 m_iLength += CSeqNo::seqlen(seqno1, seqno2); | |
176 } | |
177 else | |
178 { | |
179 m_iLastInsertPos = i; | |
180 | |
181 // overlap, coalesce with prior node, insert(3, 7) to [2, 5], ... be
comes [2, 7] | |
182 if (CSeqNo::seqcmp(m_piData2[i], seqno2) < 0) | |
183 { | |
184 m_iLength += CSeqNo::seqlen(m_piData2[i], seqno2) - 1; | |
185 m_piData2[i] = seqno2; | |
186 | |
187 loc = i; | |
188 } | |
189 else | |
190 return 0; | |
191 } | |
192 } | |
193 } | |
194 else | |
195 { | |
196 m_iLastInsertPos = m_iHead; | |
197 | |
198 // insert to head node | |
199 if (seqno2 != seqno1) | |
200 { | |
201 if (-1 == m_piData2[loc]) | |
202 { | |
203 m_iLength += CSeqNo::seqlen(seqno1, seqno2) - 1; | |
204 m_piData2[loc] = seqno2; | |
205 } | |
206 else if (CSeqNo::seqcmp(seqno2, m_piData2[loc]) > 0) | |
207 { | |
208 m_iLength += CSeqNo::seqlen(m_piData2[loc], seqno2) - 1; | |
209 m_piData2[loc] = seqno2; | |
210 } | |
211 else | |
212 return 0; | |
213 } | |
214 else | |
215 return 0; | |
216 } | |
217 | |
218 // coalesce with next node. E.g., [3, 7], ..., [6, 9] becomes [3, 9] | |
219 while ((-1 != m_piNext[loc]) && (-1 != m_piData2[loc])) | |
220 { | |
221 int i = m_piNext[loc]; | |
222 | |
223 if (CSeqNo::seqcmp(m_piData1[i], CSeqNo::incseq(m_piData2[loc])) <= 0) | |
224 { | |
225 // coalesce if there is overlap | |
226 if (-1 != m_piData2[i]) | |
227 { | |
228 if (CSeqNo::seqcmp(m_piData2[i], m_piData2[loc]) > 0) | |
229 { | |
230 if (CSeqNo::seqcmp(m_piData2[loc], m_piData1[i]) >= 0) | |
231 m_iLength -= CSeqNo::seqlen(m_piData1[i], m_piData2[loc]); | |
232 | |
233 m_piData2[loc] = m_piData2[i]; | |
234 } | |
235 else | |
236 m_iLength -= CSeqNo::seqlen(m_piData1[i], m_piData2[i]); | |
237 } | |
238 else | |
239 { | |
240 if (m_piData1[i] == CSeqNo::incseq(m_piData2[loc])) | |
241 m_piData2[loc] = m_piData1[i]; | |
242 else | |
243 m_iLength --; | |
244 } | |
245 | |
246 m_piData1[i] = -1; | |
247 m_piData2[i] = -1; | |
248 m_piNext[loc] = m_piNext[i]; | |
249 } | |
250 else | |
251 break; | |
252 } | |
253 | |
254 return m_iLength - origlen; | |
255 } | |
256 | |
257 void CSndLossList::remove(const int32_t& seqno) | |
258 { | |
259 CGuard listguard(m_ListLock); | |
260 | |
261 if (0 == m_iLength) | |
262 return; | |
263 | |
264 // Remove all from the head pointer to a node with a larger seq. no. or the l
ist is empty | |
265 int offset = CSeqNo::seqoff(m_piData1[m_iHead], seqno); | |
266 int loc = (m_iHead + offset + m_iSize) % m_iSize; | |
267 | |
268 if (0 == offset) | |
269 { | |
270 // It is the head. Remove the head and point to the next node | |
271 loc = (loc + 1) % m_iSize; | |
272 | |
273 if (-1 == m_piData2[m_iHead]) | |
274 loc = m_piNext[m_iHead]; | |
275 else | |
276 { | |
277 m_piData1[loc] = CSeqNo::incseq(seqno); | |
278 if (CSeqNo::seqcmp(m_piData2[m_iHead], CSeqNo::incseq(seqno)) > 0) | |
279 m_piData2[loc] = m_piData2[m_iHead]; | |
280 | |
281 m_piData2[m_iHead] = -1; | |
282 | |
283 m_piNext[loc] = m_piNext[m_iHead]; | |
284 } | |
285 | |
286 m_piData1[m_iHead] = -1; | |
287 | |
288 if (m_iLastInsertPos == m_iHead) | |
289 m_iLastInsertPos = -1; | |
290 | |
291 m_iHead = loc; | |
292 | |
293 m_iLength --; | |
294 } | |
295 else if (offset > 0) | |
296 { | |
297 int h = m_iHead; | |
298 | |
299 if (seqno == m_piData1[loc]) | |
300 { | |
301 // target node is not empty, remove part/all of the seqno in the node. | |
302 int temp = loc; | |
303 loc = (loc + 1) % m_iSize; | |
304 | |
305 if (-1 == m_piData2[temp]) | |
306 m_iHead = m_piNext[temp]; | |
307 else | |
308 { | |
309 // remove part, e.g., [3, 7] becomes [], [4, 7] after remove(3) | |
310 m_piData1[loc] = CSeqNo::incseq(seqno); | |
311 if (CSeqNo::seqcmp(m_piData2[temp], m_piData1[loc]) > 0) | |
312 m_piData2[loc] = m_piData2[temp]; | |
313 m_iHead = loc; | |
314 m_piNext[loc] = m_piNext[temp]; | |
315 m_piNext[temp] = loc; | |
316 m_piData2[temp] = -1; | |
317 } | |
318 } | |
319 else | |
320 { | |
321 // target node is empty, check prior node | |
322 int i = m_iHead; | |
323 while ((-1 != m_piNext[i]) && (CSeqNo::seqcmp(m_piData1[m_piNext[i]], s
eqno) < 0)) | |
324 i = m_piNext[i]; | |
325 | |
326 loc = (loc + 1) % m_iSize; | |
327 | |
328 if (-1 == m_piData2[i]) | |
329 m_iHead = m_piNext[i]; | |
330 else if (CSeqNo::seqcmp(m_piData2[i], seqno) > 0) | |
331 { | |
332 // remove part/all seqno in the prior node | |
333 m_piData1[loc] = CSeqNo::incseq(seqno); | |
334 if (CSeqNo::seqcmp(m_piData2[i], m_piData1[loc]) > 0) | |
335 m_piData2[loc] = m_piData2[i]; | |
336 | |
337 m_piData2[i] = seqno; | |
338 | |
339 m_piNext[loc] = m_piNext[i]; | |
340 m_piNext[i] = loc; | |
341 | |
342 m_iHead = loc; | |
343 } | |
344 else | |
345 m_iHead = m_piNext[i]; | |
346 } | |
347 | |
348 // Remove all nodes prior to the new head | |
349 while (h != m_iHead) | |
350 { | |
351 if (m_piData2[h] != -1) | |
352 { | |
353 m_iLength -= CSeqNo::seqlen(m_piData1[h], m_piData2[h]); | |
354 m_piData2[h] = -1; | |
355 } | |
356 else | |
357 m_iLength --; | |
358 | |
359 m_piData1[h] = -1; | |
360 | |
361 if (m_iLastInsertPos == h) | |
362 m_iLastInsertPos = -1; | |
363 | |
364 h = m_piNext[h]; | |
365 } | |
366 } | |
367 } | |
368 | |
369 int CSndLossList::getLossLength() | |
370 { | |
371 CGuard listguard(m_ListLock); | |
372 | |
373 return m_iLength; | |
374 } | |
375 | |
376 int32_t CSndLossList::getLostSeq() | |
377 { | |
378 if (0 == m_iLength) | |
379 return -1; | |
380 | |
381 CGuard listguard(m_ListLock); | |
382 | |
383 if (0 == m_iLength) | |
384 return -1; | |
385 | |
386 if (m_iLastInsertPos == m_iHead) | |
387 m_iLastInsertPos = -1; | |
388 | |
389 // return the first loss seq. no. | |
390 int32_t seqno = m_piData1[m_iHead]; | |
391 | |
392 // head moves to the next node | |
393 if (-1 == m_piData2[m_iHead]) | |
394 { | |
395 //[3, -1] becomes [], and head moves to next node in the list | |
396 m_piData1[m_iHead] = -1; | |
397 m_iHead = m_piNext[m_iHead]; | |
398 } | |
399 else | |
400 { | |
401 // shift to next node, e.g., [3, 7] becomes [], [4, 7] | |
402 int loc = (m_iHead + 1) % m_iSize; | |
403 | |
404 m_piData1[loc] = CSeqNo::incseq(seqno); | |
405 if (CSeqNo::seqcmp(m_piData2[m_iHead], m_piData1[loc]) > 0) | |
406 m_piData2[loc] = m_piData2[m_iHead]; | |
407 | |
408 m_piData1[m_iHead] = -1; | |
409 m_piData2[m_iHead] = -1; | |
410 | |
411 m_piNext[loc] = m_piNext[m_iHead]; | |
412 m_iHead = loc; | |
413 } | |
414 | |
415 m_iLength --; | |
416 | |
417 return seqno; | |
418 } | |
419 | |
420 //////////////////////////////////////////////////////////////////////////////// | |
421 | |
422 CRcvLossList::CRcvLossList(const int& size): | |
423 m_piData1(NULL), | |
424 m_piData2(NULL), | |
425 m_piNext(NULL), | |
426 m_piPrior(NULL), | |
427 m_iHead(-1), | |
428 m_iTail(-1), | |
429 m_iLength(0), | |
430 m_iSize(size) | |
431 { | |
432 m_piData1 = new int32_t [m_iSize]; | |
433 m_piData2 = new int32_t [m_iSize]; | |
434 m_piNext = new int [m_iSize]; | |
435 m_piPrior = new int [m_iSize]; | |
436 | |
437 // -1 means there is no data in the node | |
438 for (int i = 0; i < size; ++ i) | |
439 { | |
440 m_piData1[i] = -1; | |
441 m_piData2[i] = -1; | |
442 } | |
443 } | |
444 | |
445 CRcvLossList::~CRcvLossList() | |
446 { | |
447 delete [] m_piData1; | |
448 delete [] m_piData2; | |
449 delete [] m_piNext; | |
450 delete [] m_piPrior; | |
451 } | |
452 | |
453 void CRcvLossList::insert(const int32_t& seqno1, const int32_t& seqno2) | |
454 { | |
455 // Data to be inserted must be larger than all those in the list | |
456 // guaranteed by the UDT receiver | |
457 | |
458 if (0 == m_iLength) | |
459 { | |
460 // insert data into an empty list | |
461 m_iHead = 0; | |
462 m_iTail = 0; | |
463 m_piData1[m_iHead] = seqno1; | |
464 if (seqno2 != seqno1) | |
465 m_piData2[m_iHead] = seqno2; | |
466 | |
467 m_piNext[m_iHead] = -1; | |
468 m_piPrior[m_iHead] = -1; | |
469 m_iLength += CSeqNo::seqlen(seqno1, seqno2); | |
470 | |
471 return; | |
472 } | |
473 | |
474 // otherwise searching for the position where the node should be | |
475 int offset = CSeqNo::seqoff(m_piData1[m_iHead], seqno1); | |
476 int loc = (m_iHead + offset) % m_iSize; | |
477 | |
478 if ((-1 != m_piData2[m_iTail]) && (CSeqNo::incseq(m_piData2[m_iTail]) == seqn
o1)) | |
479 { | |
480 // coalesce with prior node, e.g., [2, 5], [6, 7] becomes [2, 7] | |
481 loc = m_iTail; | |
482 m_piData2[loc] = seqno2; | |
483 } | |
484 else | |
485 { | |
486 // create new node | |
487 m_piData1[loc] = seqno1; | |
488 | |
489 if (seqno2 != seqno1) | |
490 m_piData2[loc] = seqno2; | |
491 | |
492 m_piNext[m_iTail] = loc; | |
493 m_piPrior[loc] = m_iTail; | |
494 m_piNext[loc] = -1; | |
495 m_iTail = loc; | |
496 } | |
497 | |
498 m_iLength += CSeqNo::seqlen(seqno1, seqno2); | |
499 } | |
500 | |
501 bool CRcvLossList::remove(const int32_t& seqno) | |
502 { | |
503 if (0 == m_iLength) | |
504 return false; | |
505 | |
506 // locate the position of "seqno" in the list | |
507 int offset = CSeqNo::seqoff(m_piData1[m_iHead], seqno); | |
508 if (offset < 0) | |
509 return false; | |
510 | |
511 int loc = (m_iHead + offset) % m_iSize; | |
512 | |
513 if (seqno == m_piData1[loc]) | |
514 { | |
515 // This is a seq. no. that starts the loss sequence | |
516 | |
517 if (-1 == m_piData2[loc]) | |
518 { | |
519 // there is only 1 loss in the sequence, delete it from the node | |
520 if (m_iHead == loc) | |
521 { | |
522 m_iHead = m_piNext[m_iHead]; | |
523 if (-1 != m_iHead) | |
524 m_piPrior[m_iHead] = -1; | |
525 } | |
526 else | |
527 { | |
528 m_piNext[m_piPrior[loc]] = m_piNext[loc]; | |
529 if (-1 != m_piNext[loc]) | |
530 m_piPrior[m_piNext[loc]] = m_piPrior[loc]; | |
531 else | |
532 m_iTail = m_piPrior[loc]; | |
533 } | |
534 | |
535 m_piData1[loc] = -1; | |
536 } | |
537 else | |
538 { | |
539 // there are more than 1 loss in the sequence | |
540 // move the node to the next and update the starter as the next loss in
SeqNo(seqno) | |
541 | |
542 // find next node | |
543 int i = (loc + 1) % m_iSize; | |
544 | |
545 // remove the "seqno" and change the starter as next seq. no. | |
546 m_piData1[i] = CSeqNo::incseq(m_piData1[loc]); | |
547 | |
548 // process the sequence end | |
549 if (CSeqNo::seqcmp(m_piData2[loc], CSeqNo::incseq(m_piData1[loc])) > 0) | |
550 m_piData2[i] = m_piData2[loc]; | |
551 | |
552 // remove the current node | |
553 m_piData1[loc] = -1; | |
554 m_piData2[loc] = -1; | |
555 | |
556 // update list pointer | |
557 m_piNext[i] = m_piNext[loc]; | |
558 m_piPrior[i] = m_piPrior[loc]; | |
559 | |
560 if (m_iHead == loc) | |
561 m_iHead = i; | |
562 else | |
563 m_piNext[m_piPrior[i]] = i; | |
564 | |
565 if (m_iTail == loc) | |
566 m_iTail = i; | |
567 else | |
568 m_piPrior[m_piNext[i]] = i; | |
569 } | |
570 | |
571 m_iLength --; | |
572 | |
573 return true; | |
574 } | |
575 | |
576 // There is no loss sequence in the current position | |
577 // the "seqno" may be contained in a previous node | |
578 | |
579 // searching previous node | |
580 int i = (loc - 1 + m_iSize) % m_iSize; | |
581 while (-1 == m_piData1[i]) | |
582 i = (i - 1 + m_iSize) % m_iSize; | |
583 | |
584 // not contained in this node, return | |
585 if ((-1 == m_piData2[i]) || (CSeqNo::seqcmp(seqno, m_piData2[i]) > 0)) | |
586 return false; | |
587 | |
588 if (seqno == m_piData2[i]) | |
589 { | |
590 // it is the sequence end | |
591 | |
592 if (seqno == CSeqNo::incseq(m_piData1[i])) | |
593 m_piData2[i] = -1; | |
594 else | |
595 m_piData2[i] = CSeqNo::decseq(seqno); | |
596 } | |
597 else | |
598 { | |
599 // split the sequence | |
600 | |
601 // construct the second sequence from CSeqNo::incseq(seqno) to the origina
l sequence end | |
602 // located at "loc + 1" | |
603 loc = (loc + 1) % m_iSize; | |
604 | |
605 m_piData1[loc] = CSeqNo::incseq(seqno); | |
606 if (CSeqNo::seqcmp(m_piData2[i], m_piData1[loc]) > 0) | |
607 m_piData2[loc] = m_piData2[i]; | |
608 | |
609 // the first (original) sequence is between the original sequence start to
CSeqNo::decseq(seqno) | |
610 if (seqno == CSeqNo::incseq(m_piData1[i])) | |
611 m_piData2[i] = -1; | |
612 else | |
613 m_piData2[i] = CSeqNo::decseq(seqno); | |
614 | |
615 // update the list pointer | |
616 m_piNext[loc] = m_piNext[i]; | |
617 m_piNext[i] = loc; | |
618 m_piPrior[loc] = i; | |
619 | |
620 if (m_iTail == i) | |
621 m_iTail = loc; | |
622 else | |
623 m_piPrior[m_piNext[loc]] = loc; | |
624 } | |
625 | |
626 m_iLength --; | |
627 | |
628 return true; | |
629 } | |
630 | |
631 bool CRcvLossList::remove(const int32_t& seqno1, const int32_t& seqno2) | |
632 { | |
633 if (seqno1 <= seqno2) | |
634 { | |
635 for (int32_t i = seqno1; i <= seqno2; ++ i) | |
636 remove(i); | |
637 } | |
638 else | |
639 { | |
640 for (int32_t j = seqno1; j < CSeqNo::m_iMaxSeqNo; ++ j) | |
641 remove(j); | |
642 for (int32_t k = 0; k <= seqno2; ++ k) | |
643 remove(k); | |
644 } | |
645 | |
646 return true; | |
647 } | |
648 | |
649 bool CRcvLossList::find(const int32_t& seqno1, const int32_t& seqno2) const | |
650 { | |
651 if (0 == m_iLength) | |
652 return false; | |
653 | |
654 int p = m_iHead; | |
655 | |
656 while (-1 != p) | |
657 { | |
658 if ((CSeqNo::seqcmp(m_piData1[p], seqno1) == 0) || | |
659 ((CSeqNo::seqcmp(m_piData1[p], seqno1) > 0) && (CSeqNo::seqcmp(m_piDat
a1[p], seqno2) <= 0)) || | |
660 ((CSeqNo::seqcmp(m_piData1[p], seqno1) < 0) && (m_piData2[p] != -1) &&
CSeqNo::seqcmp(m_piData2[p], seqno1) >= 0)) | |
661 return true; | |
662 | |
663 p = m_piNext[p]; | |
664 } | |
665 | |
666 return false; | |
667 } | |
668 | |
669 int CRcvLossList::getLossLength() const | |
670 { | |
671 return m_iLength; | |
672 } | |
673 | |
674 int CRcvLossList::getFirstLostSeq() const | |
675 { | |
676 if (0 == m_iLength) | |
677 return -1; | |
678 | |
679 return m_piData1[m_iHead]; | |
680 } | |
681 | |
682 void CRcvLossList::getLossArray(int32_t* array, int& len, const int& limit) | |
683 { | |
684 len = 0; | |
685 | |
686 int i = m_iHead; | |
687 | |
688 while ((len < limit - 1) && (-1 != i)) | |
689 { | |
690 array[len] = m_piData1[i]; | |
691 if (-1 != m_piData2[i]) | |
692 { | |
693 // there are more than 1 loss in the sequence | |
694 array[len] |= 0x80000000; | |
695 ++ len; | |
696 array[len] = m_piData2[i]; | |
697 } | |
698 | |
699 ++ len; | |
700 | |
701 i = m_piNext[i]; | |
702 } | |
703 } | |
OLD | NEW |