/*-------------------------------------------------------------------------- Project: HorizonSDK File: rdt_ResendQueue.cpp Copyright 2009 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Date:: 2010-09-16#$ $Rev: 26004 $ $Author: hiratsu_daisuke $ *------------------------------------------------------------------------- */ #include "stdafx.h" #include "rdt_ResendQueue.h" #include #include "Test.h" #include "rdt_Utility.h" namespace { } // End of anonymous namespace namespace nn { namespace rdt { namespace CTR { ResendQueue::ResendQueue(void) :m_bResendMode(false) { Clear(); } ResendQueue::~ResendQueue(void) { } bool ResendQueue::Push(const Segment &seg) { if(m_queue.IsFull()) { return false; } // TORIAEZU SegmentWithTime swt; swt.segment = seg; swt.timeStamp = nn::rdt::CTR::GetCurrentTimeAsMillisecond(); // Unlike data segments, SYN segments do not need to be sent at a high pace. if(seg.IsSyn()) { swt.timeOut = SYN_SEGMENT_TIMEOUT; } else { swt.timeOut = m_defaultTimeout; } if(!m_queue.IsEmpty()) { // In the new implementation, the partial order relation of time stamps is no longer guaranteed. (In send mode, the partial order relationship does not hold) // // However, since it is a problem for this function to be called in that state (= attempting to send new data before the resend process completes), this code will be left for a little longer. // // // Checks whether the time stamps for the element group recorded in the queue maintains a partial order relation. // ASSERT(swt.timeStamp >= m_queue.Back().timeStamp); } m_queue.PushBack(swt); return true; } bool ResendQueue::Front(Segment *pSeg) const { ASSERT(pSeg!=NULL); if(m_queue.IsEmpty()) { return false; } else { *pSeg = m_queue.Front().segment; return true; } } // // Remove function must be revised. Because it already cannot be assumed that the queue is arranged in the time stamp order. // // With this implementation, if the Remove function target is not at the beginning of the queue, the target is not removed. void ResendQueue::Remove(u32 ack) { while(!m_queue.IsEmpty()) { const Segment &seg = m_queue.Front().segment; u32 lastSeq = seg.GetLastSeqNumber(); if(0 < static_cast(ack) - static_cast(lastSeq)) { m_queue.PopFront(); VERBOSE("Start of the resend queue was removed. \n"); if(m_queue.IsEmpty()) { // Resend mode ends if the resend queue is empty. m_bResendMode = false; } } else { // If even the start cannot get arrival confirmation with ACK, the following segment surely won't be able to. // Leave loop. break; } } } bool ResendQueue::IsResendRequired(void) const { if(m_queue.IsEmpty()) { return false; } else { return m_queue.Front().IsTimeOut(); } } u32 ResendQueue::GetTotalDataSize(void) const { u32 ret = 0; for(size_t i= 0; i