ChunkSender: Fixed a potential crash: removing a client means that no Send() is called on that client anymore
git-svn-id: http://mc-server.googlecode.com/svn/trunk@384 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
parent
0cee2428c1
commit
4544d5d3b9
@ -31,7 +31,7 @@ cChunkSender::cChunkSender(void) :
|
||||
cChunkSender::~cChunkSender()
|
||||
{
|
||||
mShouldTerminate = true;
|
||||
m_Event.Set();
|
||||
m_evtQueue.Set();
|
||||
}
|
||||
|
||||
|
||||
@ -55,7 +55,7 @@ void cChunkSender::ChunkReady(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||
cCSLock Lock(m_CS);
|
||||
m_ChunksReady.push_back(cChunkCoords(a_ChunkX, a_ChunkY, a_ChunkZ));
|
||||
}
|
||||
m_Event.Set();
|
||||
m_evtQueue.Set();
|
||||
}
|
||||
|
||||
|
||||
@ -69,7 +69,7 @@ void cChunkSender::QueueSendChunkTo(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cC
|
||||
cCSLock Lock(m_CS);
|
||||
m_SendChunks.push_back(sSendChunk(a_ChunkX, a_ChunkY, a_ChunkZ, a_Client));
|
||||
}
|
||||
m_Event.Set();
|
||||
m_evtQueue.Set();
|
||||
}
|
||||
|
||||
|
||||
@ -78,16 +78,20 @@ void cChunkSender::QueueSendChunkTo(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cC
|
||||
|
||||
void cChunkSender::RemoveClient(cClientHandle * a_Client)
|
||||
{
|
||||
cCSLock Lock(m_CS);
|
||||
for (sSendChunkList::iterator itr = m_SendChunks.begin(); itr != m_SendChunks.end();)
|
||||
{
|
||||
if (itr->m_Client == a_Client)
|
||||
cCSLock Lock(m_CS);
|
||||
for (sSendChunkList::iterator itr = m_SendChunks.begin(); itr != m_SendChunks.end();)
|
||||
{
|
||||
itr = m_SendChunks.erase(itr);
|
||||
continue;
|
||||
}
|
||||
++itr;
|
||||
} // for itr - m_SendChunks[]
|
||||
if (itr->m_Client == a_Client)
|
||||
{
|
||||
itr = m_SendChunks.erase(itr);
|
||||
continue;
|
||||
}
|
||||
++itr;
|
||||
} // for itr - m_SendChunks[]
|
||||
}
|
||||
m_evtQueue.Set();
|
||||
m_evtRemoved.Wait(); // Wait for removal confirmation
|
||||
}
|
||||
|
||||
|
||||
@ -102,7 +106,8 @@ void cChunkSender::Execute(void)
|
||||
while (m_ChunksReady.empty() && m_SendChunks.empty())
|
||||
{
|
||||
cCSUnlock Unlock(Lock);
|
||||
m_Event.Wait();
|
||||
m_evtRemoved.Set(); // Notify that the removed clients are safe to be deleted
|
||||
m_evtQueue.Wait();
|
||||
if (mShouldTerminate)
|
||||
{
|
||||
return;
|
||||
@ -127,6 +132,7 @@ void cChunkSender::Execute(void)
|
||||
|
||||
SendChunk(Chunk.m_ChunkX, Chunk.m_ChunkY, Chunk.m_ChunkZ, Chunk.m_Client);
|
||||
}
|
||||
m_evtRemoved.Set(); // Notify that the removed clients are safe to be deleted
|
||||
} // while (!mShouldTerminate)
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,10 @@ Chunk data is queried using the cChunkDataCallback interface.
|
||||
It is cached inside the ChunkSender object during the query and then processed after the query ends.
|
||||
Note that the data needs to be compressed only *after* the query finishes,
|
||||
because the query callbacks run with ChunkMap's CS locked.
|
||||
|
||||
A client may remove itself from all direct requests(QueueSendChunkTo()) by calling RemoveClient();
|
||||
this ensures that the client's Send() won't be called anymore by ChunkSender.
|
||||
Note that it may be called by world's BroadcastToChunk() if the client is still in the chunk.
|
||||
*/
|
||||
|
||||
|
||||
@ -78,10 +82,11 @@ protected:
|
||||
|
||||
cWorld * m_World;
|
||||
|
||||
cCriticalSection m_CS;
|
||||
cChunkCoordsList m_ChunksReady;
|
||||
sSendChunkList m_SendChunks;
|
||||
cEvent m_Event; // Set when anything is added to m_ChunksReady
|
||||
cCriticalSection m_CS;
|
||||
cChunkCoordsList m_ChunksReady;
|
||||
sSendChunkList m_SendChunks;
|
||||
cEvent m_evtQueue; // Set when anything is added to m_ChunksReady
|
||||
cEvent m_evtRemoved; // Set when removed clients are safe to be deleted
|
||||
|
||||
// Data about the chunk that is being sent:
|
||||
char m_BlockData[cChunk::c_BlockDataSize];
|
||||
|
Loading…
Reference in New Issue
Block a user