From a33d9b7c3b7da9af8eacae58684bf3592b534931 Mon Sep 17 00:00:00 2001 From: lotodore Date: Tue, 9 Jun 2009 23:04:04 +0000 Subject: [PATCH] Trying to fix strange timer crashes. --- src/core/common/timermanager.cpp | 20 ++-------- src/core/timermanager.h | 2 +- src/net/common/senderhelper.cpp | 31 +++++++-------- src/net/common/servergamestate.cpp | 64 +++++++++++++++--------------- 4 files changed, 51 insertions(+), 66 deletions(-) diff --git a/src/core/common/timermanager.cpp b/src/core/common/timermanager.cpp index 6dc32499..baf6b7be 100644 --- a/src/core/common/timermanager.cpp +++ b/src/core/common/timermanager.cpp @@ -38,6 +38,7 @@ TimerManager::RegisterTimer(unsigned timeoutMsec, boost::function timerH boost::shared_ptr data(new TimerData); data->timer.reset( new boost::asio::deadline_timer(*m_ioService, boost::posix_time::milliseconds(timeoutMsec))); + data->id = id; data->userHandler = timerHandler; data->durationMsec = timeoutMsec; data->autoRestart = autoRestart; @@ -48,23 +49,6 @@ TimerManager::RegisterTimer(unsigned timeoutMsec, boost::function timerH return id; } -bool -TimerManager::AddTimer(unsigned timerId, unsigned timeoutMsec, boost::function timerHandler) -{ - boost::recursive_mutex::scoped_lock lock(m_timerMutex); - bool restarted = false; - TimerMap::iterator pos = m_timerMap.find(timerId); - if (pos != m_timerMap.end()) - { - pos->second->userHandler = timerHandler; - pos->second->timer.reset( - new boost::asio::deadline_timer(*m_ioService, boost::posix_time::milliseconds(timeoutMsec))); - pos->second->timer->async_wait(boost::bind(&TimerManager::Handler, this, boost::asio::placeholders::error, pos->second)); - restarted = true; - } - return restarted; -} - bool TimerManager::UnregisterTimer(unsigned timerId) { @@ -94,6 +78,8 @@ TimerManager::Handler(const boost::system::error_code &ec, boost::shared_ptrdurationMsec))); data->timer->async_wait(boost::bind(&TimerManager::Handler, this, boost::asio::placeholders::error, data)); } + else + UnregisterTimer(data->id); } } diff --git a/src/core/timermanager.h b/src/core/timermanager.h index 83893b7a..8f511002 100644 --- a/src/core/timermanager.h +++ b/src/core/timermanager.h @@ -32,13 +32,13 @@ public: TimerManager(boost::shared_ptr ioService); unsigned RegisterTimer(unsigned timeoutMsec, boost::function timerHandler, bool autoRestart = false); - bool AddTimer(unsigned timerId, unsigned timeoutMsec, boost::function timerHandler); bool UnregisterTimer(unsigned timerId); protected: struct TimerData { + unsigned id; boost::shared_ptr timer; boost::function userHandler; unsigned durationMsec; diff --git a/src/net/common/senderhelper.cpp b/src/net/common/senderhelper.cpp index b4347ed1..3fa2e59a 100644 --- a/src/net/common/senderhelper.cpp +++ b/src/net/common/senderhelper.cpp @@ -26,7 +26,6 @@ #include #include -#include using namespace std; using boost::asio::ip::tcp; @@ -40,11 +39,11 @@ using boost::asio::ip::tcp; typedef std::list > SendDataList; -class SendDataManager : public boost::enable_shared_from_this +class SendDataManager { public: - SendDataManager(boost::shared_ptr s) - : socket(s), sendBuf(NULL), writeInProgress(false) + SendDataManager() + : sendBuf(NULL), writeInProgress(false) { } @@ -53,11 +52,9 @@ class SendDataManager : public boost::enable_shared_from_this delete[] sendBuf; } - void HandleWrite(const boost::system::error_code &error); + void HandleWrite(boost::shared_ptr socket, const boost::system::error_code &error); - void AsyncSendNextPacket(bool handlerMode = false); - - boost::shared_ptr socket; + void AsyncSendNextPacket(boost::shared_ptr socket, bool handlerMode = false); mutable boost::mutex dataMutex; SendDataList list; @@ -67,15 +64,15 @@ class SendDataManager : public boost::enable_shared_from_this void -SendDataManager::HandleWrite(const boost::system::error_code &error) +SendDataManager::HandleWrite(boost::shared_ptr socket, const boost::system::error_code &error) { // TODO error handling if (!error) - AsyncSendNextPacket(true); + AsyncSendNextPacket(socket, true); } void -SendDataManager::AsyncSendNextPacket(bool handlerMode) +SendDataManager::AsyncSendNextPacket(boost::shared_ptr socket, bool handlerMode) { boost::mutex::scoped_lock lock(dataMutex); if (!writeInProgress || handlerMode) @@ -108,7 +105,9 @@ SendDataManager::AsyncSendNextPacket(bool handlerMode) boost::asio::async_write( *socket, boost::asio::buffer(sendBuf, bufSize), - boost::bind(&SendDataManager::HandleWrite, shared_from_this(), + boost::bind(&SendDataManager::HandleWrite, + this, + socket, boost::asio::placeholders::error)); writeInProgress = true; } @@ -137,7 +136,7 @@ SenderHelper::Send(boost::shared_ptr session, boost::shared_ptrGetId()); if (pos == m_sendQueueMap.end()) - pos = m_sendQueueMap.insert(SendQueueMap::value_type(session->GetId(), boost::shared_ptr(new SendDataManager(session->GetAsioSocket())))).first; + pos = m_sendQueueMap.insert(SendQueueMap::value_type(session->GetId(), boost::shared_ptr(new SendDataManager))).first; tmpManager = pos->second; } { @@ -150,7 +149,7 @@ SenderHelper::Send(boost::shared_ptr session, boost::shared_ptrAsyncSendNextPacket(); + tmpManager->AsyncSendNextPacket(session->GetAsioSocket()); } } } @@ -166,7 +165,7 @@ SenderHelper::Send(boost::shared_ptr session, const NetPacketList & boost::mutex::scoped_lock lock(m_sendQueueMapMutex); SendQueueMap::iterator pos = m_sendQueueMap.find(session->GetId()); if (pos == m_sendQueueMap.end()) - pos = m_sendQueueMap.insert(SendQueueMap::value_type(session->GetId(), boost::shared_ptr(new SendDataManager(session->GetAsioSocket())))).first; + pos = m_sendQueueMap.insert(SendQueueMap::value_type(session->GetId(), boost::shared_ptr(new SendDataManager))).first; tmpManager = pos->second; } { @@ -185,7 +184,7 @@ SenderHelper::Send(boost::shared_ptr session, const NetPacketList & } { // Third: Activate async send, if needed. - tmpManager->AsyncSendNextPacket(); + tmpManager->AsyncSendNextPacket(session->GetAsioSocket()); } } } diff --git a/src/net/common/servergamestate.cpp b/src/net/common/servergamestate.cpp index f90ef46e..2d3eb415 100644 --- a/src/net/common/servergamestate.cpp +++ b/src/net/common/servergamestate.cpp @@ -400,10 +400,10 @@ ServerGameStateInit::TimerAdminWarning(ServerGame &server) server.GetLobbyThread().GetSender().Send(session.sessionData, warning); } // Start timeout timer. - server.GetLobbyThread().GetTimerManager().AddTimer( - server.GetStateTimerId(), - SERVER_GAME_ADMIN_WARNING_REMAINING_SEC * 1000, - boost::bind(&ServerGameStateInit::TimerAdminTimeout, this, boost::ref(server))); + server.SetStateTimerId( + server.GetLobbyThread().GetTimerManager().RegisterTimer( + SERVER_GAME_ADMIN_WARNING_REMAINING_SEC * 1000, + boost::bind(&ServerGameStateInit::TimerAdminTimeout, this, boost::ref(server)))); } void @@ -701,19 +701,19 @@ ServerGameStateHand::TimerLoop(ServerGame &server) server.SendToAllPlayers(allIn, SessionData::Game); curGame.getCurrentHand()->setCardsShown(true); - server.GetLobbyThread().GetTimerManager().AddTimer( - server.GetStateTimerId(), - SERVER_SHOW_CARDS_DELAY_SEC * 1000, - boost::bind(&ServerGameStateHand::TimerLoop, this, boost::ref(server))); + server.SetStateTimerId( + server.GetLobbyThread().GetTimerManager().RegisterTimer( + SERVER_SHOW_CARDS_DELAY_SEC * 1000, + boost::bind(&ServerGameStateHand::TimerLoop, this, boost::ref(server)))); } else { SendNewRoundCards(server, curGame, newRound); - server.GetLobbyThread().GetTimerManager().AddTimer( - server.GetStateTimerId(), - GetDealCardsDelaySec(server) * 1000, - boost::bind(&ServerGameStateHand::TimerLoop, this, boost::ref(server))); + server.SetStateTimerId( + server.GetLobbyThread().GetTimerManager().RegisterTimer( + GetDealCardsDelaySec(server) * 1000, + boost::bind(&ServerGameStateHand::TimerLoop, this, boost::ref(server)))); } } else @@ -741,19 +741,19 @@ ServerGameStateHand::TimerLoop(ServerGame &server) // If the player is computer controlled, let the engine act. if (curPlayer->getMyType() == PLAYER_TYPE_COMPUTER) { - server.GetLobbyThread().GetTimerManager().AddTimer( - server.GetStateTimerId(), - SERVER_COMPUTER_ACTION_DELAY_SEC * 1000, - boost::bind(&ServerGameStateHand::TimerComputerAction, this, boost::ref(server))); + server.SetStateTimerId( + server.GetLobbyThread().GetTimerManager().RegisterTimer( + SERVER_COMPUTER_ACTION_DELAY_SEC * 1000, + boost::bind(&ServerGameStateHand::TimerComputerAction, this, boost::ref(server)))); } // If the player we are waiting for left, continue without him. else if (!server.GetSessionManager().IsPlayerConnected(curPlayer->getMyName())) { PerformPlayerAction(server, curPlayer, PLAYER_ACTION_FOLD, 0); - server.GetLobbyThread().GetTimerManager().AddTimer( - server.GetStateTimerId(), - SERVER_LOOP_DELAY_MSEC, - boost::bind(&ServerGameStateHand::TimerLoop, this, boost::ref(server))); + server.SetStateTimerId( + server.GetLobbyThread().GetTimerManager().RegisterTimer( + SERVER_LOOP_DELAY_MSEC, + boost::bind(&ServerGameStateHand::TimerLoop, this, boost::ref(server)))); } else { @@ -833,17 +833,17 @@ ServerGameStateHand::TimerLoop(ServerGame &server) else if (playersWithCash.size() == 1) { // View a dialog for a new game - delayed. - server.GetLobbyThread().GetTimerManager().AddTimer( - server.GetStateTimerId(), - SERVER_DELAY_NEXT_GAME_SEC * 1000, - boost::bind(&ServerGameStateHand::TimerNextGame, this, boost::ref(server))); + server.SetStateTimerId( + server.GetLobbyThread().GetTimerManager().RegisterTimer( + SERVER_DELAY_NEXT_GAME_SEC * 1000, + boost::bind(&ServerGameStateHand::TimerNextGame, this, boost::ref(server)))); } else { - server.GetLobbyThread().GetTimerManager().AddTimer( - server.GetStateTimerId(), - SERVER_DELAY_NEXT_HAND_SEC * 1000, - boost::bind(&ServerGameStateHand::TimerNextHand, this, boost::ref(server))); + server.SetStateTimerId( + server.GetLobbyThread().GetTimerManager().RegisterTimer( + SERVER_DELAY_NEXT_HAND_SEC * 1000, + boost::bind(&ServerGameStateHand::TimerNextHand, this, boost::ref(server)))); } } } @@ -855,10 +855,10 @@ ServerGameStateHand::TimerShowCards(ServerGame &server) Game &curGame = server.GetGame(); SendNewRoundCards(server, curGame, curGame.getCurrentHand()->getCurrentRound()); - server.GetLobbyThread().GetTimerManager().AddTimer( - server.GetStateTimerId(), - GetDealCardsDelaySec(server) * 1000, - boost::bind(&ServerGameStateHand::TimerLoop, this, boost::ref(server))); + server.SetStateTimerId( + server.GetLobbyThread().GetTimerManager().RegisterTimer( + GetDealCardsDelaySec(server) * 1000, + boost::bind(&ServerGameStateHand::TimerLoop, this, boost::ref(server)))); } void