Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(114)

Side by Side Diff: net/third_party/udt/src/list.cpp

Issue 6708091: Remove UDT. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/third_party/udt/src/list.h ('k') | net/third_party/udt/src/md5.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 }
OLDNEW
« no previous file with comments | « net/third_party/udt/src/list.h ('k') | net/third_party/udt/src/md5.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698