aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2016-02-22 20:02:26 +0100
committerShauren <shauren.trinity@gmail.com>2016-02-22 20:02:26 +0100
commit8086a39210659c44d52fb463f5a39f047aa45685 (patch)
tree79cea67d774381245097ebed54c0963ddaef6cc6 /src
parent346b9c1534644197846f32a11090fc82c84713f0 (diff)
Core/PacketIO: Requeue packets handled with STATUS_LOGGEDIN received before player is fully loaded in one step after packet processing loop - reduces used locks from 3 per packet to 1 per packet
Diffstat (limited to 'src')
-rw-r--r--src/common/Threading/LockedQueue.h8
-rw-r--r--src/server/game/Server/WorldSession.cpp23
2 files changed, 15 insertions, 16 deletions
diff --git a/src/common/Threading/LockedQueue.h b/src/common/Threading/LockedQueue.h
index c6faaaf81ca..21a29d7e53b 100644
--- a/src/common/Threading/LockedQueue.h
+++ b/src/common/Threading/LockedQueue.h
@@ -57,6 +57,14 @@ public:
unlock();
}
+ //! Adds items back to front of the queue
+ template<class Iterator>
+ void readd(Iterator begin, Iterator end)
+ {
+ std::lock_guard<std::mutex> lock(_lock);
+ _queue.insert(_queue.begin(), begin, end);
+ }
+
//! Gets the next result in the queue, if any.
bool next(T& result)
{
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index 0092a35c811..78e7bbfc180 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -341,17 +341,11 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
WorldPacket* packet = NULL;
//! Delete packet after processing by default
bool deletePacket = true;
- //! To prevent infinite loop
- WorldPacket* firstDelayedPacket = NULL;
- //! If _recvQueue.peek() == firstDelayedPacket it means that in this Update call, we've processed all
- //! *properly timed* packets, and we're now at the part of the queue where we find
- //! delayed packets that were re-enqueued due to improper timing. To prevent an infinite
- //! loop caused by re-enqueueing the same packets over and over again, we stop updating this session
- //! and continue updating others. The re-enqueued packets will be handled in the next Update call for this session.
+ std::vector<WorldPacket*> requeuePackets;
uint32 processedPackets = 0;
time_t currentTime = time(NULL);
- while (m_Socket[CONNECTION_TYPE_REALM] && !_recvQueue.empty() && _recvQueue.peek(true) != firstDelayedPacket && _recvQueue.next(packet, updater))
+ while (m_Socket[CONNECTION_TYPE_REALM] && _recvQueue.next(packet, updater))
{
ClientOpcodeHandler const* opHandle = opcodeTable[static_cast<OpcodeClient>(packet->GetOpcode())];
try
@@ -366,15 +360,10 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
//! the client to be in world yet. We will re-add the packets to the bottom of the queue and process them later.
if (!m_playerRecentlyLogout)
{
- //! Prevent infinite loop
- if (!firstDelayedPacket)
- firstDelayedPacket = packet;
- //! Because checking a bool is faster than reallocating memory
+ requeuePackets.push_back(packet);
deletePacket = false;
- QueuePacket(packet);
- //! Log
- TC_LOG_DEBUG("network", "Re-enqueueing packet with opcode %s with with status STATUS_LOGGEDIN. "
- "Player is currently not in world yet.", GetOpcodeNameForLogging(static_cast<OpcodeClient>(packet->GetOpcode())).c_str());
+ TC_LOG_DEBUG("network", "Re-enqueueing packet with opcode %s with with status STATUS_LOGGEDIN. "
+ "Player is currently not in world yet.", GetOpcodeNameForLogging(static_cast<OpcodeClient>(packet->GetOpcode())).c_str());
}
}
else if (_player->IsInWorld() && AntiDOS.EvaluateOpcode(*packet, currentTime))
@@ -465,6 +454,8 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
break;
}
+ _recvQueue.readd(requeuePackets.begin(), requeuePackets.end());
+
if (m_Socket[CONNECTION_TYPE_REALM] && m_Socket[CONNECTION_TYPE_REALM]->IsOpen() && _warden)
_warden->Update();