Fixed a problem in the SenderThread, where packet order was not maintained when a session had stalled packets in the send buffer.

This commit is contained in:
lotodore
2008-04-23 21:19:00 +00:00
parent 85435f0ce5
commit df97fcc725
3 changed files with 44 additions and 19 deletions
+40 -14
View File
@@ -49,8 +49,18 @@ SenderThread::Send(boost::shared_ptr<SessionData> session, boost::shared_ptr<Net
{ {
if (packet.get() && session.get()) if (packet.get() && session.get())
{ {
boost::mutex::scoped_lock lock(m_sendQueueMutex); boost::mutex::scoped_lock lock0(m_sessionsStalledMutex);
InternalStore(m_sendQueue, SEND_QUEUE_SIZE, session, packet); if (find(m_sessionsStalled.begin(), m_sessionsStalled.end(), session->GetId()) == m_sessionsStalled.end())
{
boost::mutex::scoped_lock lock1(m_sendQueueMutex);
InternalStore(m_sendQueue, SEND_QUEUE_SIZE, session, packet);
}
else
{
// This session is stalled.
boost::mutex::scoped_lock lock2(m_stalledQueueMutex);
InternalStore(m_stalledQueue, SEND_QUEUE_SIZE, session, packet);
}
} }
} }
@@ -59,8 +69,18 @@ SenderThread::Send(boost::shared_ptr<SessionData> session, const NetPacketList &
{ {
if (!packetList.empty() && session.get()) if (!packetList.empty() && session.get())
{ {
boost::mutex::scoped_lock lock(m_sendQueueMutex); boost::mutex::scoped_lock lock0(m_sessionsStalledMutex);
InternalStore(m_sendQueue, SEND_QUEUE_SIZE, session, packetList); if (find(m_sessionsStalled.begin(), m_sessionsStalled.end(), session->GetId()) == m_sessionsStalled.end())
{
boost::mutex::scoped_lock lock1(m_sendQueueMutex);
InternalStore(m_sendQueue, SEND_QUEUE_SIZE, session, packetList);
}
else
{
// This session is stalled.
boost::mutex::scoped_lock lock2(m_stalledQueueMutex);
InternalStore(m_stalledQueue, SEND_QUEUE_SIZE, session, packetList);
}
} }
} }
@@ -69,11 +89,11 @@ SenderThread::GetNumPacketsInQueue() const
{ {
unsigned numPackets; unsigned numPackets;
{ {
boost::mutex::scoped_lock lock(m_sendQueueMutex); boost::mutex::scoped_lock lock1(m_sendQueueMutex);
numPackets = m_sendQueue.size(); numPackets = m_sendQueue.size();
} }
{ {
boost::mutex::scoped_lock lock(m_stalledQueueMutex); boost::mutex::scoped_lock lock2(m_stalledQueueMutex);
numPackets += m_stalledQueue.size(); numPackets += m_stalledQueue.size();
} }
return numPackets; return numPackets;
@@ -149,14 +169,18 @@ SenderThread::Main()
SendData tmpData; SendData tmpData;
// Check main queue. // Check main queue.
{ {
boost::mutex::scoped_lock lock(m_sendQueueMutex); boost::mutex::scoped_lock lock0(m_sessionsStalledMutex);
boost::mutex::scoped_lock lock1(m_sendQueueMutex);
if (m_sendQueue.empty()) if (m_sendQueue.empty())
{ {
// Check stalled queue. // Check stalled queue.
// Attention: double lock (on purpose). // Attention: TRIPLE lock (on purpose).
boost::mutex::scoped_lock lock2(m_stalledQueueMutex); boost::mutex::scoped_lock lock2(m_stalledQueueMutex);
if (!m_stalledQueue.empty()) if (!m_stalledQueue.empty())
{
m_sendQueue.swap(m_stalledQueue); m_sendQueue.swap(m_stalledQueue);
m_sessionsStalled.clear(); // No more sessions stalled, all in send list.
}
} }
if (!m_sendQueue.empty()) if (!m_sendQueue.empty())
{ {
@@ -207,11 +231,13 @@ SenderThread::Main()
{ {
// A timeout occured - don't block the thread. // A timeout occured - don't block the thread.
{ {
// Attention: double lock (on purpose). // Attention: TRIPLE lock (on purpose).
// Stall all packets for that sender. // Stall all packets for that sender.
boost::mutex::scoped_lock lock(m_sendQueueMutex); boost::mutex::scoped_lock lock0(m_sessionsStalledMutex);
boost::mutex::scoped_lock lock1(m_sendQueueMutex);
boost::mutex::scoped_lock lock2(m_stalledQueueMutex); boost::mutex::scoped_lock lock2(m_stalledQueueMutex);
m_stalledQueue.push_back(tmpData); m_stalledQueue.push_back(tmpData);
m_sessionsStalled.push_back(tmpData.session->GetId());
SendDataList::iterator i = m_sendQueue.begin(); SendDataList::iterator i = m_sendQueue.begin();
SendDataList::iterator end = m_sendQueue.end(); SendDataList::iterator end = m_sendQueue.end();
while (i != end) while (i != end)
@@ -230,7 +256,7 @@ SenderThread::Main()
else else
{ {
// Select was successful - store the packet back in the main queue. // Select was successful - store the packet back in the main queue.
boost::mutex::scoped_lock lock(m_sendQueueMutex); boost::mutex::scoped_lock lock1(m_sendQueueMutex);
m_sendQueue.push_front(tmpData); m_sendQueue.push_front(tmpData);
} }
} }
@@ -249,7 +275,7 @@ SenderThread::Main()
{ {
tmpData.bytesSent += bytesSent; tmpData.bytesSent += bytesSent;
// Send was partly successful - store the packet back in the main queue. // Send was partly successful - store the packet back in the main queue.
boost::mutex::scoped_lock lock(m_sendQueueMutex); boost::mutex::scoped_lock lock1(m_sendQueueMutex);
m_sendQueue.push_front(tmpData); m_sendQueue.push_front(tmpData);
} }
else else
@@ -267,11 +293,11 @@ SenderThread::Main()
unsigned sendQueueSize = 0; unsigned sendQueueSize = 0;
unsigned stalledQueueSize = 0; unsigned stalledQueueSize = 0;
{ {
boost::mutex::scoped_lock lock(m_sendQueueMutex); boost::mutex::scoped_lock lock1(m_sendQueueMutex);
sendQueueSize = m_sendQueue.size(); sendQueueSize = m_sendQueue.size();
} }
{ {
boost::mutex::scoped_lock lock(m_stalledQueueMutex); boost::mutex::scoped_lock lock2(m_stalledQueueMutex);
stalledQueueSize = m_stalledQueue.size(); stalledQueueSize = m_stalledQueue.size();
} }
LOG_VERBOSE("Sender TICK - send queue " << sendQueueSize << ", stalled " << stalledQueueSize << "."); LOG_VERBOSE("Sender TICK - send queue " << sendQueueSize << ", stalled " << stalledQueueSize << ".");
+4
View File
@@ -56,6 +56,7 @@ protected:
unsigned bytesSent; unsigned bytesSent;
}; };
typedef std::list<SendData> SendDataList; typedef std::list<SendData> SendDataList;
typedef std::list<SessionId> SessionIdList;
// Main function of the thread. // Main function of the thread.
virtual void Main(); virtual void Main();
@@ -71,6 +72,9 @@ private:
SendDataList m_stalledQueue; SendDataList m_stalledQueue;
mutable boost::mutex m_stalledQueueMutex; mutable boost::mutex m_stalledQueueMutex;
SessionIdList m_sessionsStalled; // Cache
mutable boost::mutex m_sessionsStalledMutex;
SenderCallback &m_callback; SenderCallback &m_callback;
boost::timers::portable::microsec_timer m_logTimer; boost::timers::portable::microsec_timer m_logTimer;
-5
View File
@@ -32,11 +32,6 @@
#define SESSION_ID_GENERIC 0xFFFFFFFF #define SESSION_ID_GENERIC 0xFFFFFFFF
typedef unsigned SessionId; typedef unsigned SessionId;
/*struct SessionId
{
unsigned id;
};*/
class SessionData class SessionData
{ {