Index: net/third_party/udt/src/list.cpp |
=================================================================== |
--- net/third_party/udt/src/list.cpp (revision 78992) |
+++ net/third_party/udt/src/list.cpp (working copy) |
@@ -1,703 +0,0 @@ |
-/***************************************************************************** |
-Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. |
-All rights reserved. |
- |
-Redistribution and use in source and binary forms, with or without |
-modification, are permitted provided that the following conditions are |
-met: |
- |
-* Redistributions of source code must retain the above |
- copyright notice, this list of conditions and the |
- following disclaimer. |
- |
-* Redistributions in binary form must reproduce the |
- above copyright notice, this list of conditions |
- and the following disclaimer in the documentation |
- and/or other materials provided with the distribution. |
- |
-* Neither the name of the University of Illinois |
- nor the names of its contributors may be used to |
- endorse or promote products derived from this |
- software without specific prior written permission. |
- |
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS |
-IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
-PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
-CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
-PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
-*****************************************************************************/ |
- |
-/***************************************************************************** |
-written by |
- Yunhong Gu, last updated 01/22/2011 |
-*****************************************************************************/ |
- |
-#include "list.h" |
- |
-CSndLossList::CSndLossList(const int& size): |
-m_piData1(NULL), |
-m_piData2(NULL), |
-m_piNext(NULL), |
-m_iHead(-1), |
-m_iLength(0), |
-m_iSize(size), |
-m_iLastInsertPos(-1), |
-m_ListLock() |
-{ |
- m_piData1 = new int32_t [m_iSize]; |
- m_piData2 = new int32_t [m_iSize]; |
- m_piNext = new int [m_iSize]; |
- |
- // -1 means there is no data in the node |
- for (int i = 0; i < size; ++ i) |
- { |
- m_piData1[i] = -1; |
- m_piData2[i] = -1; |
- } |
- |
- // sender list needs mutex protection |
- #ifndef WIN32 |
- pthread_mutex_init(&m_ListLock, 0); |
- #else |
- m_ListLock = CreateMutex(NULL, false, NULL); |
- #endif |
-} |
- |
-CSndLossList::~CSndLossList() |
-{ |
- delete [] m_piData1; |
- delete [] m_piData2; |
- delete [] m_piNext; |
- |
- #ifndef WIN32 |
- pthread_mutex_destroy(&m_ListLock); |
- #else |
- CloseHandle(m_ListLock); |
- #endif |
-} |
- |
-int CSndLossList::insert(const int32_t& seqno1, const int32_t& seqno2) |
-{ |
- CGuard listguard(m_ListLock); |
- |
- if (0 == m_iLength) |
- { |
- // insert data into an empty list |
- |
- m_iHead = 0; |
- m_piData1[m_iHead] = seqno1; |
- if (seqno2 != seqno1) |
- m_piData2[m_iHead] = seqno2; |
- |
- m_piNext[m_iHead] = -1; |
- m_iLastInsertPos = m_iHead; |
- |
- m_iLength += CSeqNo::seqlen(seqno1, seqno2); |
- |
- return m_iLength; |
- } |
- |
- // otherwise find the position where the data can be inserted |
- int origlen = m_iLength; |
- int offset = CSeqNo::seqoff(m_piData1[m_iHead], seqno1); |
- int loc = (m_iHead + offset + m_iSize) % m_iSize; |
- |
- if (offset < 0) |
- { |
- // Insert data prior to the head pointer |
- |
- m_piData1[loc] = seqno1; |
- if (seqno2 != seqno1) |
- m_piData2[loc] = seqno2; |
- |
- // new node becomes head |
- m_piNext[loc] = m_iHead; |
- m_iHead = loc; |
- m_iLastInsertPos = loc; |
- |
- m_iLength += CSeqNo::seqlen(seqno1, seqno2); |
- } |
- else if (offset > 0) |
- { |
- if (seqno1 == m_piData1[loc]) |
- { |
- m_iLastInsertPos = loc; |
- |
- // first seqno is equivlent, compare the second |
- if (-1 == m_piData2[loc]) |
- { |
- if (seqno2 != seqno1) |
- { |
- m_iLength += CSeqNo::seqlen(seqno1, seqno2) - 1; |
- m_piData2[loc] = seqno2; |
- } |
- } |
- else if (CSeqNo::seqcmp(seqno2, m_piData2[loc]) > 0) |
- { |
- // new seq pair is longer than old pair, e.g., insert [3, 7] to [3, 5], becomes [3, 7] |
- m_iLength += CSeqNo::seqlen(m_piData2[loc], seqno2) - 1; |
- m_piData2[loc] = seqno2; |
- } |
- else |
- // Do nothing if it is already there |
- return 0; |
- } |
- else |
- { |
- // searching the prior node |
- int i; |
- if ((-1 != m_iLastInsertPos) && (CSeqNo::seqcmp(m_piData1[m_iLastInsertPos], seqno1) < 0)) |
- i = m_iLastInsertPos; |
- else |
- i = m_iHead; |
- |
- while ((-1 != m_piNext[i]) && (CSeqNo::seqcmp(m_piData1[m_piNext[i]], seqno1) < 0)) |
- i = m_piNext[i]; |
- |
- if ((-1 == m_piData2[i]) || (CSeqNo::seqcmp(m_piData2[i], seqno1) < 0)) |
- { |
- m_iLastInsertPos = loc; |
- |
- // no overlap, create new node |
- m_piData1[loc] = seqno1; |
- if (seqno2 != seqno1) |
- m_piData2[loc] = seqno2; |
- |
- m_piNext[loc] = m_piNext[i]; |
- m_piNext[i] = loc; |
- |
- m_iLength += CSeqNo::seqlen(seqno1, seqno2); |
- } |
- else |
- { |
- m_iLastInsertPos = i; |
- |
- // overlap, coalesce with prior node, insert(3, 7) to [2, 5], ... becomes [2, 7] |
- if (CSeqNo::seqcmp(m_piData2[i], seqno2) < 0) |
- { |
- m_iLength += CSeqNo::seqlen(m_piData2[i], seqno2) - 1; |
- m_piData2[i] = seqno2; |
- |
- loc = i; |
- } |
- else |
- return 0; |
- } |
- } |
- } |
- else |
- { |
- m_iLastInsertPos = m_iHead; |
- |
- // insert to head node |
- if (seqno2 != seqno1) |
- { |
- if (-1 == m_piData2[loc]) |
- { |
- m_iLength += CSeqNo::seqlen(seqno1, seqno2) - 1; |
- m_piData2[loc] = seqno2; |
- } |
- else if (CSeqNo::seqcmp(seqno2, m_piData2[loc]) > 0) |
- { |
- m_iLength += CSeqNo::seqlen(m_piData2[loc], seqno2) - 1; |
- m_piData2[loc] = seqno2; |
- } |
- else |
- return 0; |
- } |
- else |
- return 0; |
- } |
- |
- // coalesce with next node. E.g., [3, 7], ..., [6, 9] becomes [3, 9] |
- while ((-1 != m_piNext[loc]) && (-1 != m_piData2[loc])) |
- { |
- int i = m_piNext[loc]; |
- |
- if (CSeqNo::seqcmp(m_piData1[i], CSeqNo::incseq(m_piData2[loc])) <= 0) |
- { |
- // coalesce if there is overlap |
- if (-1 != m_piData2[i]) |
- { |
- if (CSeqNo::seqcmp(m_piData2[i], m_piData2[loc]) > 0) |
- { |
- if (CSeqNo::seqcmp(m_piData2[loc], m_piData1[i]) >= 0) |
- m_iLength -= CSeqNo::seqlen(m_piData1[i], m_piData2[loc]); |
- |
- m_piData2[loc] = m_piData2[i]; |
- } |
- else |
- m_iLength -= CSeqNo::seqlen(m_piData1[i], m_piData2[i]); |
- } |
- else |
- { |
- if (m_piData1[i] == CSeqNo::incseq(m_piData2[loc])) |
- m_piData2[loc] = m_piData1[i]; |
- else |
- m_iLength --; |
- } |
- |
- m_piData1[i] = -1; |
- m_piData2[i] = -1; |
- m_piNext[loc] = m_piNext[i]; |
- } |
- else |
- break; |
- } |
- |
- return m_iLength - origlen; |
-} |
- |
-void CSndLossList::remove(const int32_t& seqno) |
-{ |
- CGuard listguard(m_ListLock); |
- |
- if (0 == m_iLength) |
- return; |
- |
- // Remove all from the head pointer to a node with a larger seq. no. or the list is empty |
- int offset = CSeqNo::seqoff(m_piData1[m_iHead], seqno); |
- int loc = (m_iHead + offset + m_iSize) % m_iSize; |
- |
- if (0 == offset) |
- { |
- // It is the head. Remove the head and point to the next node |
- loc = (loc + 1) % m_iSize; |
- |
- if (-1 == m_piData2[m_iHead]) |
- loc = m_piNext[m_iHead]; |
- else |
- { |
- m_piData1[loc] = CSeqNo::incseq(seqno); |
- if (CSeqNo::seqcmp(m_piData2[m_iHead], CSeqNo::incseq(seqno)) > 0) |
- m_piData2[loc] = m_piData2[m_iHead]; |
- |
- m_piData2[m_iHead] = -1; |
- |
- m_piNext[loc] = m_piNext[m_iHead]; |
- } |
- |
- m_piData1[m_iHead] = -1; |
- |
- if (m_iLastInsertPos == m_iHead) |
- m_iLastInsertPos = -1; |
- |
- m_iHead = loc; |
- |
- m_iLength --; |
- } |
- else if (offset > 0) |
- { |
- int h = m_iHead; |
- |
- if (seqno == m_piData1[loc]) |
- { |
- // target node is not empty, remove part/all of the seqno in the node. |
- int temp = loc; |
- loc = (loc + 1) % m_iSize; |
- |
- if (-1 == m_piData2[temp]) |
- m_iHead = m_piNext[temp]; |
- else |
- { |
- // remove part, e.g., [3, 7] becomes [], [4, 7] after remove(3) |
- m_piData1[loc] = CSeqNo::incseq(seqno); |
- if (CSeqNo::seqcmp(m_piData2[temp], m_piData1[loc]) > 0) |
- m_piData2[loc] = m_piData2[temp]; |
- m_iHead = loc; |
- m_piNext[loc] = m_piNext[temp]; |
- m_piNext[temp] = loc; |
- m_piData2[temp] = -1; |
- } |
- } |
- else |
- { |
- // target node is empty, check prior node |
- int i = m_iHead; |
- while ((-1 != m_piNext[i]) && (CSeqNo::seqcmp(m_piData1[m_piNext[i]], seqno) < 0)) |
- i = m_piNext[i]; |
- |
- loc = (loc + 1) % m_iSize; |
- |
- if (-1 == m_piData2[i]) |
- m_iHead = m_piNext[i]; |
- else if (CSeqNo::seqcmp(m_piData2[i], seqno) > 0) |
- { |
- // remove part/all seqno in the prior node |
- m_piData1[loc] = CSeqNo::incseq(seqno); |
- if (CSeqNo::seqcmp(m_piData2[i], m_piData1[loc]) > 0) |
- m_piData2[loc] = m_piData2[i]; |
- |
- m_piData2[i] = seqno; |
- |
- m_piNext[loc] = m_piNext[i]; |
- m_piNext[i] = loc; |
- |
- m_iHead = loc; |
- } |
- else |
- m_iHead = m_piNext[i]; |
- } |
- |
- // Remove all nodes prior to the new head |
- while (h != m_iHead) |
- { |
- if (m_piData2[h] != -1) |
- { |
- m_iLength -= CSeqNo::seqlen(m_piData1[h], m_piData2[h]); |
- m_piData2[h] = -1; |
- } |
- else |
- m_iLength --; |
- |
- m_piData1[h] = -1; |
- |
- if (m_iLastInsertPos == h) |
- m_iLastInsertPos = -1; |
- |
- h = m_piNext[h]; |
- } |
- } |
-} |
- |
-int CSndLossList::getLossLength() |
-{ |
- CGuard listguard(m_ListLock); |
- |
- return m_iLength; |
-} |
- |
-int32_t CSndLossList::getLostSeq() |
-{ |
- if (0 == m_iLength) |
- return -1; |
- |
- CGuard listguard(m_ListLock); |
- |
- if (0 == m_iLength) |
- return -1; |
- |
- if (m_iLastInsertPos == m_iHead) |
- m_iLastInsertPos = -1; |
- |
- // return the first loss seq. no. |
- int32_t seqno = m_piData1[m_iHead]; |
- |
- // head moves to the next node |
- if (-1 == m_piData2[m_iHead]) |
- { |
- //[3, -1] becomes [], and head moves to next node in the list |
- m_piData1[m_iHead] = -1; |
- m_iHead = m_piNext[m_iHead]; |
- } |
- else |
- { |
- // shift to next node, e.g., [3, 7] becomes [], [4, 7] |
- int loc = (m_iHead + 1) % m_iSize; |
- |
- m_piData1[loc] = CSeqNo::incseq(seqno); |
- if (CSeqNo::seqcmp(m_piData2[m_iHead], m_piData1[loc]) > 0) |
- m_piData2[loc] = m_piData2[m_iHead]; |
- |
- m_piData1[m_iHead] = -1; |
- m_piData2[m_iHead] = -1; |
- |
- m_piNext[loc] = m_piNext[m_iHead]; |
- m_iHead = loc; |
- } |
- |
- m_iLength --; |
- |
- return seqno; |
-} |
- |
-//////////////////////////////////////////////////////////////////////////////// |
- |
-CRcvLossList::CRcvLossList(const int& size): |
-m_piData1(NULL), |
-m_piData2(NULL), |
-m_piNext(NULL), |
-m_piPrior(NULL), |
-m_iHead(-1), |
-m_iTail(-1), |
-m_iLength(0), |
-m_iSize(size) |
-{ |
- m_piData1 = new int32_t [m_iSize]; |
- m_piData2 = new int32_t [m_iSize]; |
- m_piNext = new int [m_iSize]; |
- m_piPrior = new int [m_iSize]; |
- |
- // -1 means there is no data in the node |
- for (int i = 0; i < size; ++ i) |
- { |
- m_piData1[i] = -1; |
- m_piData2[i] = -1; |
- } |
-} |
- |
-CRcvLossList::~CRcvLossList() |
-{ |
- delete [] m_piData1; |
- delete [] m_piData2; |
- delete [] m_piNext; |
- delete [] m_piPrior; |
-} |
- |
-void CRcvLossList::insert(const int32_t& seqno1, const int32_t& seqno2) |
-{ |
- // Data to be inserted must be larger than all those in the list |
- // guaranteed by the UDT receiver |
- |
- if (0 == m_iLength) |
- { |
- // insert data into an empty list |
- m_iHead = 0; |
- m_iTail = 0; |
- m_piData1[m_iHead] = seqno1; |
- if (seqno2 != seqno1) |
- m_piData2[m_iHead] = seqno2; |
- |
- m_piNext[m_iHead] = -1; |
- m_piPrior[m_iHead] = -1; |
- m_iLength += CSeqNo::seqlen(seqno1, seqno2); |
- |
- return; |
- } |
- |
- // otherwise searching for the position where the node should be |
- int offset = CSeqNo::seqoff(m_piData1[m_iHead], seqno1); |
- int loc = (m_iHead + offset) % m_iSize; |
- |
- if ((-1 != m_piData2[m_iTail]) && (CSeqNo::incseq(m_piData2[m_iTail]) == seqno1)) |
- { |
- // coalesce with prior node, e.g., [2, 5], [6, 7] becomes [2, 7] |
- loc = m_iTail; |
- m_piData2[loc] = seqno2; |
- } |
- else |
- { |
- // create new node |
- m_piData1[loc] = seqno1; |
- |
- if (seqno2 != seqno1) |
- m_piData2[loc] = seqno2; |
- |
- m_piNext[m_iTail] = loc; |
- m_piPrior[loc] = m_iTail; |
- m_piNext[loc] = -1; |
- m_iTail = loc; |
- } |
- |
- m_iLength += CSeqNo::seqlen(seqno1, seqno2); |
-} |
- |
-bool CRcvLossList::remove(const int32_t& seqno) |
-{ |
- if (0 == m_iLength) |
- return false; |
- |
- // locate the position of "seqno" in the list |
- int offset = CSeqNo::seqoff(m_piData1[m_iHead], seqno); |
- if (offset < 0) |
- return false; |
- |
- int loc = (m_iHead + offset) % m_iSize; |
- |
- if (seqno == m_piData1[loc]) |
- { |
- // This is a seq. no. that starts the loss sequence |
- |
- if (-1 == m_piData2[loc]) |
- { |
- // there is only 1 loss in the sequence, delete it from the node |
- if (m_iHead == loc) |
- { |
- m_iHead = m_piNext[m_iHead]; |
- if (-1 != m_iHead) |
- m_piPrior[m_iHead] = -1; |
- } |
- else |
- { |
- m_piNext[m_piPrior[loc]] = m_piNext[loc]; |
- if (-1 != m_piNext[loc]) |
- m_piPrior[m_piNext[loc]] = m_piPrior[loc]; |
- else |
- m_iTail = m_piPrior[loc]; |
- } |
- |
- m_piData1[loc] = -1; |
- } |
- else |
- { |
- // there are more than 1 loss in the sequence |
- // move the node to the next and update the starter as the next loss inSeqNo(seqno) |
- |
- // find next node |
- int i = (loc + 1) % m_iSize; |
- |
- // remove the "seqno" and change the starter as next seq. no. |
- m_piData1[i] = CSeqNo::incseq(m_piData1[loc]); |
- |
- // process the sequence end |
- if (CSeqNo::seqcmp(m_piData2[loc], CSeqNo::incseq(m_piData1[loc])) > 0) |
- m_piData2[i] = m_piData2[loc]; |
- |
- // remove the current node |
- m_piData1[loc] = -1; |
- m_piData2[loc] = -1; |
- |
- // update list pointer |
- m_piNext[i] = m_piNext[loc]; |
- m_piPrior[i] = m_piPrior[loc]; |
- |
- if (m_iHead == loc) |
- m_iHead = i; |
- else |
- m_piNext[m_piPrior[i]] = i; |
- |
- if (m_iTail == loc) |
- m_iTail = i; |
- else |
- m_piPrior[m_piNext[i]] = i; |
- } |
- |
- m_iLength --; |
- |
- return true; |
- } |
- |
- // There is no loss sequence in the current position |
- // the "seqno" may be contained in a previous node |
- |
- // searching previous node |
- int i = (loc - 1 + m_iSize) % m_iSize; |
- while (-1 == m_piData1[i]) |
- i = (i - 1 + m_iSize) % m_iSize; |
- |
- // not contained in this node, return |
- if ((-1 == m_piData2[i]) || (CSeqNo::seqcmp(seqno, m_piData2[i]) > 0)) |
- return false; |
- |
- if (seqno == m_piData2[i]) |
- { |
- // it is the sequence end |
- |
- if (seqno == CSeqNo::incseq(m_piData1[i])) |
- m_piData2[i] = -1; |
- else |
- m_piData2[i] = CSeqNo::decseq(seqno); |
- } |
- else |
- { |
- // split the sequence |
- |
- // construct the second sequence from CSeqNo::incseq(seqno) to the original sequence end |
- // located at "loc + 1" |
- loc = (loc + 1) % m_iSize; |
- |
- m_piData1[loc] = CSeqNo::incseq(seqno); |
- if (CSeqNo::seqcmp(m_piData2[i], m_piData1[loc]) > 0) |
- m_piData2[loc] = m_piData2[i]; |
- |
- // the first (original) sequence is between the original sequence start to CSeqNo::decseq(seqno) |
- if (seqno == CSeqNo::incseq(m_piData1[i])) |
- m_piData2[i] = -1; |
- else |
- m_piData2[i] = CSeqNo::decseq(seqno); |
- |
- // update the list pointer |
- m_piNext[loc] = m_piNext[i]; |
- m_piNext[i] = loc; |
- m_piPrior[loc] = i; |
- |
- if (m_iTail == i) |
- m_iTail = loc; |
- else |
- m_piPrior[m_piNext[loc]] = loc; |
- } |
- |
- m_iLength --; |
- |
- return true; |
-} |
- |
-bool CRcvLossList::remove(const int32_t& seqno1, const int32_t& seqno2) |
-{ |
- if (seqno1 <= seqno2) |
- { |
- for (int32_t i = seqno1; i <= seqno2; ++ i) |
- remove(i); |
- } |
- else |
- { |
- for (int32_t j = seqno1; j < CSeqNo::m_iMaxSeqNo; ++ j) |
- remove(j); |
- for (int32_t k = 0; k <= seqno2; ++ k) |
- remove(k); |
- } |
- |
- return true; |
-} |
- |
-bool CRcvLossList::find(const int32_t& seqno1, const int32_t& seqno2) const |
-{ |
- if (0 == m_iLength) |
- return false; |
- |
- int p = m_iHead; |
- |
- while (-1 != p) |
- { |
- if ((CSeqNo::seqcmp(m_piData1[p], seqno1) == 0) || |
- ((CSeqNo::seqcmp(m_piData1[p], seqno1) > 0) && (CSeqNo::seqcmp(m_piData1[p], seqno2) <= 0)) || |
- ((CSeqNo::seqcmp(m_piData1[p], seqno1) < 0) && (m_piData2[p] != -1) && CSeqNo::seqcmp(m_piData2[p], seqno1) >= 0)) |
- return true; |
- |
- p = m_piNext[p]; |
- } |
- |
- return false; |
-} |
- |
-int CRcvLossList::getLossLength() const |
-{ |
- return m_iLength; |
-} |
- |
-int CRcvLossList::getFirstLostSeq() const |
-{ |
- if (0 == m_iLength) |
- return -1; |
- |
- return m_piData1[m_iHead]; |
-} |
- |
-void CRcvLossList::getLossArray(int32_t* array, int& len, const int& limit) |
-{ |
- len = 0; |
- |
- int i = m_iHead; |
- |
- while ((len < limit - 1) && (-1 != i)) |
- { |
- array[len] = m_piData1[i]; |
- if (-1 != m_piData2[i]) |
- { |
- // there are more than 1 loss in the sequence |
- array[len] |= 0x80000000; |
- ++ len; |
- array[len] = m_piData2[i]; |
- } |
- |
- ++ len; |
- |
- i = m_piNext[i]; |
- } |
-} |