#include "precompiled.h" #include "Session.h" #include "Network.h" #include "ps/CLogger.h" using namespace std; void CSessionManager::Register(CNetSession *pSession) { CScopeLock scopeLock(m_Mutex); SessionMap::iterator it; // The total number of references to this session should be 1 and only 1 // Either there's one in m_Sessions or there's one in m_AddQueue. There // shall be no references in the remove queue. // m_Sessions is Read-Only if ((it = m_RemoveQueue.find(pSession)) != m_RemoveQueue.end()) m_RemoveQueue.erase(it); if (m_Sessions.find(pSession) == m_Sessions.end()) m_AddQueue[pSession]=pSession; } void CSessionManager::Deregister(CNetSession *pSession) { CScopeLock scopeLock(m_Mutex); SessionMap::iterator it; // The total number of references to this session should be 2 or 0: // One in m_Sessions and one in the remove queue or 0 in both. None in // m_AddQueue. // m_Sessions is Read-Only if ((it = m_AddQueue.find(pSession)) != m_AddQueue.end()) m_AddQueue.erase(it); if (m_Sessions.find(pSession) != m_Sessions.end()) m_RemoveQueue.insert(make_pair(pSession, pSession)); } void CSessionManager::Poll() { m_Mutex.Lock(); SessionMap::iterator it; // De/Register should've made sure that it doesn't matter which order we // process the two queues. for (it=m_AddQueue.begin();it != m_AddQueue.end();++it) { m_Sessions.insert(*it); } m_AddQueue.clear(); for (it=m_RemoveQueue.begin();it != m_RemoveQueue.end();++it) { m_Sessions.erase(it->second); } m_RemoveQueue.clear(); it=m_Sessions.begin(); while (it != m_Sessions.end()) { CNetMessage *pMsg; // Extraneous? well, sessions are perfectly able to delete other // sessions (or cause them to be deleted) in their message handler if (m_RemoveQueue.find(it->second) != m_RemoveQueue.end()) continue; while ((pMsg = it->second->TryPop()) != NULL) { CNetSession *pSess=it->second; m_Mutex.Unlock(); if (!pSess->HandleMessage(pMsg)) { LOG(WARNING, LOG_CAT_NET, "CSessionManager::Poll(): Unhandled message %s.", pMsg->GetString().c_str()); delete pMsg; } m_Mutex.Lock(); if (m_RemoveQueue.find(it->second) != m_RemoveQueue.end()) break; } ++it; } m_Mutex.Unlock(); }