- Use ACE_Future and ACE_Future_Set for async SQL queries with callback
* Callbacks will now be executed from the thread and object that scheduled the request, instead of the world runnable thread (and thus are no longer dependent on the 50ms forced sleep time).
* This design gets rid of a potential DOS loophole in the resultqueue system - unique requests will be cancelled when re-requested.
- Drop now redundant SQLQueryTask, SQLResultQueue, SQLResultQueueTask operations.
- Drop now redundant CharacterHandler class
- Change static callback functions in WorldSession to normal functions.

Thanks to Derex and Zor for advice along the way.

--HG--
branch : trunk
This commit is contained in:
Machiavelli
2010-08-18 19:48:51 +02:00
parent 2ffe785765
commit d845a903b1
15 changed files with 303 additions and 862 deletions
@@ -59,7 +59,6 @@
#include "OutdoorPvPMgr.h"
#include "ArenaTeam.h"
#include "Chat.h"
#include "AsyncDatabaseImpl.h"
#include "Spell.h"
#include "SocialMgr.h"
#include "GameEventMgr.h"
@@ -27,7 +27,6 @@
#include "WorldSession.h"
#include "MD5.h"
#include "DatabaseEnv.h"
#include "AsyncDatabaseImpl.h"
#include "ArenaTeam.h"
#include "Chat.h"
@@ -103,33 +102,6 @@ bool LoginQueryHolder::Initialize()
return res;
}
// don't call WorldSession directly
// it may get deleted before the query callbacks get executed
// instead pass an account id to this handler
class CharacterHandler
{
public:
void HandleCharEnumCallback(QueryResult_AutoPtr result, uint32 account)
{
WorldSession * session = sWorld.FindSession(account);
if (!session)
return;
session->HandleCharEnum(result);
}
void HandlePlayerLoginCallback(QueryResult_AutoPtr /*dummy*/, SQLQueryHolder * holder)
{
if (!holder) return;
WorldSession *session = sWorld.FindSession(((LoginQueryHolder*)holder)->GetAccountId());
if (!session)
{
delete holder;
return;
}
session->HandlePlayerLogin((LoginQueryHolder*)holder);
}
} chrHandler;
void WorldSession::HandleCharEnum(QueryResult_AutoPtr result)
{
WorldPacket data(SMSG_CHAR_ENUM, 100); // we guess size
@@ -158,7 +130,8 @@ void WorldSession::HandleCharEnum(QueryResult_AutoPtr result)
void WorldSession::HandleCharEnumOpcode(WorldPacket & /*recv_data*/)
{
/// get all the data necessary for loading all characters (along with their pets) on the account
CharacterDatabase.AsyncPQuery(&chrHandler, &CharacterHandler::HandleCharEnumCallback, GetAccountId(),
m_charEnumCallback =
CharacterDatabase.AsyncPQuery(
!sWorld.getConfig(CONFIG_DECLINED_NAMES_USED) ?
// ------- Query Without Declined Names --------
// 0 1 2 3 4 5 6 7
@@ -182,7 +155,8 @@ void WorldSession::HandleCharEnumOpcode(WorldPacket & /*recv_data*/)
"LEFT JOIN character_declinedname ON characters.guid = character_declinedname.guid "
"LEFT JOIN guild_member ON characters.guid = guild_member.guid "
"WHERE characters.account = '%u' ORDER BY characters.guid",
PET_SAVE_AS_CURRENT,GetAccountId());
PET_SAVE_AS_CURRENT, GetAccountId()
);
}
void WorldSession::HandleCharCreateOpcode(WorldPacket & recv_data)
@@ -565,7 +539,7 @@ void WorldSession::HandlePlayerLoginOpcode(WorldPacket & recv_data)
return;
}
CharacterDatabase.DelayQueryHolder(&chrHandler, &CharacterHandler::HandlePlayerLoginCallback, holder);
m_charLoginCallback = CharacterDatabase.DelayQueryHolder((SQLQueryHolder*)holder);
}
void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder)
@@ -957,24 +931,22 @@ void WorldSession::HandleCharRenameOpcode(WorldPacket& recv_data)
// make sure that the character belongs to the current account, that rename at login is enabled
// and that there is no character with the desired new name
CharacterDatabase.AsyncPQuery(&WorldSession::HandleChangePlayerNameOpcodeCallBack,
GetAccountId(), newname,
m_charRenameCallback.SetParam(newname);
m_charRenameCallback.SetFutureResult(
CharacterDatabase.AsyncPQuery(
"SELECT guid, name FROM characters WHERE guid = %d AND account = %d AND (at_login & %d) = %d AND NOT EXISTS (SELECT NULL FROM characters WHERE name = '%s')",
GUID_LOPART(guid), GetAccountId(), AT_LOGIN_RENAME, AT_LOGIN_RENAME, escaped_newname.c_str()
)
);
}
void WorldSession::HandleChangePlayerNameOpcodeCallBack(QueryResult_AutoPtr result, uint32 accountId, std::string newname)
void WorldSession::HandleChangePlayerNameOpcodeCallBack(QueryResult_AutoPtr result, std::string newname)
{
WorldSession * session = sWorld.FindSession(accountId);
if (!session)
return;
if (!result)
{
WorldPacket data(SMSG_CHAR_RENAME, 1);
data << uint8(CHAR_CREATE_ERROR);
session->SendPacket(&data);
SendPacket(&data);
return;
}
@@ -985,13 +957,13 @@ void WorldSession::HandleChangePlayerNameOpcodeCallBack(QueryResult_AutoPtr resu
CharacterDatabase.PExecute("UPDATE characters set name = '%s', at_login = at_login & ~ %u WHERE guid ='%u'", newname.c_str(), uint32(AT_LOGIN_RENAME), guidLow);
CharacterDatabase.PExecute("DELETE FROM character_declinedname WHERE guid ='%u'", guidLow);
sLog.outChar("Account: %d (IP: %s) Character:[%s] (guid:%u) Changed name to: %s", session->GetAccountId(), session->GetRemoteAddress().c_str(), oldname.c_str(), guidLow, newname.c_str());
sLog.outChar("Account: %d (IP: %s) Character:[%s] (guid:%u) Changed name to: %s", GetAccountId(), GetRemoteAddress().c_str(), oldname.c_str(), guidLow, newname.c_str());
WorldPacket data(SMSG_CHAR_RENAME, 1+8+(newname.size()+1));
data << uint8(RESPONSE_SUCCESS);
data << uint64(guid);
data << newname;
session->SendPacket(&data);
SendPacket(&data);
}
void WorldSession::HandleSetPlayerDeclinedNames(WorldPacket& recv_data)
@@ -21,7 +21,6 @@
#include "Common.h"
#include "Language.h"
#include "DatabaseEnv.h"
#include "AsyncDatabaseImpl.h"
#include "WorldPacket.h"
#include "Opcodes.h"
#include "Log.h"
@@ -554,21 +553,19 @@ void WorldSession::HandleAddFriendOpcode(WorldPacket & recv_data)
sLog.outDebug("WORLD: %s asked to add friend : '%s'",
GetPlayer()->GetName(), friendName.c_str());
CharacterDatabase.AsyncPQuery(&WorldSession::HandleAddFriendOpcodeCallBack, GetAccountId(), friendNote, "SELECT guid, race, account FROM characters WHERE name = '%s'", friendName.c_str());
m_addFriendCallback.SetParam(friendNote);
m_addFriendCallback.SetFutureResult(
CharacterDatabase.AsyncPQuery("SELECT guid, race, account FROM characters WHERE name = '%s'", friendName.c_str())
);
}
void WorldSession::HandleAddFriendOpcodeCallBack(QueryResult_AutoPtr result, uint32 accountId, std::string friendNote)
void WorldSession::HandleAddFriendOpcodeCallBack(QueryResult_AutoPtr result, std::string friendNote)
{
uint64 friendGuid;
uint64 friendAcctid;
uint32 team;
FriendsResult friendResult;
WorldSession * session = sWorld.FindSession(accountId);
if (!session || !session->GetPlayer())
return;
friendResult = FRIEND_NOT_FOUND;
friendGuid = 0;
@@ -578,35 +575,35 @@ void WorldSession::HandleAddFriendOpcodeCallBack(QueryResult_AutoPtr result, uin
team = Player::TeamForRace((*result)[1].GetUInt8());
friendAcctid = (*result)[2].GetUInt32();
if (session->GetSecurity() >= SEC_MODERATOR || sWorld.getConfig(CONFIG_ALLOW_GM_FRIEND) || sAccountMgr.GetSecurity(friendAcctid) < SEC_MODERATOR)
if (GetSecurity() >= SEC_MODERATOR || sWorld.getConfig(CONFIG_ALLOW_GM_FRIEND) || sAccountMgr.GetSecurity(friendAcctid) < SEC_MODERATOR)
{
if (friendGuid)
{
if (friendGuid == session->GetPlayer()->GetGUID())
if (friendGuid == GetPlayer()->GetGUID())
friendResult = FRIEND_SELF;
else if (session->GetPlayer()->GetTeam() != team && !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND) && session->GetSecurity() < SEC_MODERATOR)
else if (GetPlayer()->GetTeam() != team && !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND) && GetSecurity() < SEC_MODERATOR)
friendResult = FRIEND_ENEMY;
else if (session->GetPlayer()->GetSocial()->HasFriend(GUID_LOPART(friendGuid)))
else if (GetPlayer()->GetSocial()->HasFriend(GUID_LOPART(friendGuid)))
friendResult = FRIEND_ALREADY;
else
{
Player* pFriend = ObjectAccessor::FindPlayer(friendGuid);
if (pFriend && pFriend->IsInWorld() && pFriend->IsVisibleGloballyFor(session->GetPlayer()))
if (pFriend && pFriend->IsInWorld() && pFriend->IsVisibleGloballyFor(GetPlayer()))
friendResult = FRIEND_ADDED_ONLINE;
else
friendResult = FRIEND_ADDED_OFFLINE;
if (!session->GetPlayer()->GetSocial()->AddToSocialList(GUID_LOPART(friendGuid), false))
if (!GetPlayer()->GetSocial()->AddToSocialList(GUID_LOPART(friendGuid), false))
{
friendResult = FRIEND_LIST_FULL;
sLog.outDebug("WORLD: %s's friend list is full.", session->GetPlayer()->GetName());
sLog.outDebug("WORLD: %s's friend list is full.", GetPlayer()->GetName());
}
}
session->GetPlayer()->GetSocial()->SetFriendNote(GUID_LOPART(friendGuid), friendNote);
GetPlayer()->GetSocial()->SetFriendNote(GUID_LOPART(friendGuid), friendNote);
}
}
}
sSocialMgr.SendFriendStatus(session->GetPlayer(), friendResult, GUID_LOPART(friendGuid), false);
sSocialMgr.SendFriendStatus(GetPlayer(), friendResult, GUID_LOPART(friendGuid), false);
sLog.outDebug("WORLD: Sent (SMSG_FRIEND_STATUS)");
}
@@ -642,19 +639,14 @@ void WorldSession::HandleAddIgnoreOpcode(WorldPacket & recv_data)
sLog.outDebug("WORLD: %s asked to Ignore: '%s'",
GetPlayer()->GetName(), IgnoreName.c_str());
CharacterDatabase.AsyncPQuery(&WorldSession::HandleAddIgnoreOpcodeCallBack, GetAccountId(), "SELECT guid FROM characters WHERE name = '%s'", IgnoreName.c_str());
m_addIgnoreCallback = CharacterDatabase.AsyncPQuery("SELECT guid FROM characters WHERE name = '%s'", IgnoreName.c_str());
}
void WorldSession::HandleAddIgnoreOpcodeCallBack(QueryResult_AutoPtr result, uint32 accountId)
void WorldSession::HandleAddIgnoreOpcodeCallBack(QueryResult_AutoPtr result)
{
uint64 IgnoreGuid;
FriendsResult ignoreResult;
WorldSession * session = sWorld.FindSession(accountId);
if (!session || !session->GetPlayer())
return;
ignoreResult = FRIEND_IGNORE_NOT_FOUND;
IgnoreGuid = 0;
@@ -664,22 +656,22 @@ void WorldSession::HandleAddIgnoreOpcodeCallBack(QueryResult_AutoPtr result, uin
if (IgnoreGuid)
{
if (IgnoreGuid == session->GetPlayer()->GetGUID()) //not add yourself
if (IgnoreGuid == GetPlayer()->GetGUID()) //not add yourself
ignoreResult = FRIEND_IGNORE_SELF;
else if (session->GetPlayer()->GetSocial()->HasIgnore(GUID_LOPART(IgnoreGuid)))
else if (GetPlayer()->GetSocial()->HasIgnore(GUID_LOPART(IgnoreGuid)))
ignoreResult = FRIEND_IGNORE_ALREADY;
else
{
ignoreResult = FRIEND_IGNORE_ADDED;
// ignore list full
if (!session->GetPlayer()->GetSocial()->AddToSocialList(GUID_LOPART(IgnoreGuid), true))
if (!GetPlayer()->GetSocial()->AddToSocialList(GUID_LOPART(IgnoreGuid), true))
ignoreResult = FRIEND_IGNORE_FULL;
}
}
}
sSocialMgr.SendFriendStatus(session->GetPlayer(), ignoreResult, GUID_LOPART(IgnoreGuid), false);
sSocialMgr.SendFriendStatus(GetPlayer(), ignoreResult, GUID_LOPART(IgnoreGuid), false);
sLog.outDebug("WORLD: Sent (SMSG_FRIEND_STATUS)");
}
@@ -21,7 +21,6 @@
#include "Common.h"
#include "Language.h"
#include "DatabaseEnv.h"
#include "AsyncDatabaseImpl.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "Opcodes.h"
@@ -61,7 +60,8 @@ void WorldSession::SendNameQueryOpcode(Player *p)
void WorldSession::SendNameQueryOpcodeFromDB(uint64 guid)
{
CharacterDatabase.AsyncPQuery(&WorldSession::SendNameQueryOpcodeFromDBCallBack, GetAccountId(),
m_nameQueryCallbacks.insert(
CharacterDatabase.AsyncPQuery(
!sWorld.getConfig(CONFIG_DECLINED_NAMES_USED) ?
// ------- Query Without Declined Names --------
// 0 1 2 3 4
@@ -74,24 +74,23 @@ void WorldSession::SendNameQueryOpcodeFromDB(uint64 guid)
// 5 6 7 8 9
"genitive, dative, accusative, instrumental, prepositional "
"FROM characters LEFT JOIN character_declinedname ON characters.guid = character_declinedname.guid WHERE characters.guid = '%u'",
GUID_LOPART(guid));
GUID_LOPART(guid))
);
// CharacterDatabase.AsyncPQuery(&WorldSession::SendNameQueryOpcodeFromDBCallBack, GetAccountId(),
}
void WorldSession::SendNameQueryOpcodeFromDBCallBack(QueryResult_AutoPtr result, uint32 accountId)
void WorldSession::SendNameQueryOpcodeFromDBCallBack(QueryResult_AutoPtr result)
{
if (!result)
return;
WorldSession * session = sWorld.FindSession(accountId);
if (!session)
return;
Field *fields = result->Fetch();
uint32 guid = fields[0].GetUInt32();
std::string name = fields[1].GetCppString();
uint8 pRace = 0, pGender = 0, pClass = 0;
if (name == "")
name = session->GetTrinityString(LANG_NON_EXIST_CHARACTER);
name = GetTrinityString(LANG_NON_EXIST_CHARACTER);
else
{
pRace = fields[2].GetUInt8();
@@ -118,7 +117,7 @@ void WorldSession::SendNameQueryOpcodeFromDBCallBack(QueryResult_AutoPtr result,
else
data << uint8(0); // is not declined
session->SendPacket(&data);
SendPacket(&data);
}
void WorldSession::HandleNameQueryOpcode(WorldPacket & recv_data)
+62
View File
@@ -290,6 +290,8 @@ bool WorldSession::Update(uint32 diff)
delete packet;
}
ProcessQueryCallbacks();
time_t currTime = time(NULL);
///- If necessary, log the player out
if (ShouldLogOut(currTime) && !m_playerLoading)
@@ -955,3 +957,63 @@ void WorldSession::SetPlayer(Player *plr)
if (_player)
m_GUIDLow = _player->GetGUIDLow();
}
void WorldSession::ProcessQueryCallbacks()
{
QueryResult_AutoPtr result;
//! HandleNameQueryOpcode
while (!m_nameQueryCallbacks.is_empty())
{
QueryResultFuture lResult;
ACE_Time_Value timeout = ACE_Time_Value::zero;
if (m_nameQueryCallbacks.next_readable(lResult, &timeout) != 1)
break;
lResult.get(result);
SendNameQueryOpcodeFromDBCallBack(result);
}
//! HandleCharEnumOpcode
if (m_charEnumCallback.ready())
{
m_charEnumCallback.get(result);
HandleCharEnum(result);
m_charEnumCallback.cancel();
}
//! HandlePlayerLoginOpcode
if (m_charLoginCallback.ready())
{
SQLQueryHolder* param;
m_charLoginCallback.get(param);
HandlePlayerLogin((LoginQueryHolder*)param);
m_charLoginCallback.cancel();
}
//! HandleAddFriendOpcode
if (m_addFriendCallback.IsReady())
{
std::string& param = m_addFriendCallback.GetParam();
m_addFriendCallback.GetResult(result);
HandleAddFriendOpcodeCallBack(result, param);
m_addFriendCallback.FreeResult();
}
//- HandleCharRenameOpcode
if (m_charRenameCallback.IsReady())
{
std::string& param = m_charRenameCallback.GetParam();
m_charRenameCallback.GetResult(result);
HandleChangePlayerNameOpcodeCallBack(result, param);
m_charRenameCallback.FreeResult();
}
//- HandleCharAddIgnoreOpcode
if (m_addIgnoreCallback.ready())
{
m_addIgnoreCallback.get(result);
HandleAddIgnoreOpcodeCallBack(result);
m_addIgnoreCallback.cancel();
}
}
+15 -4
View File
@@ -192,7 +192,7 @@ class WorldSession
//void SendTestCreatureQueryOpcode(uint32 entry, uint64 guid, uint32 testvalue);
void SendNameQueryOpcode(Player* p);
void SendNameQueryOpcodeFromDB(uint64 guid);
static void SendNameQueryOpcodeFromDBCallBack(QueryResult_AutoPtr result, uint32 accountId);
void SendNameQueryOpcodeFromDBCallBack(QueryResult_AutoPtr result);
void SendTrainerList(uint64 guid);
void SendTrainerList(uint64 guid, const std::string& strTitle);
@@ -389,10 +389,10 @@ class WorldSession
void HandleEmoteOpcode(WorldPacket& recvPacket);
void HandleContactListOpcode(WorldPacket& recvPacket);
void HandleAddFriendOpcode(WorldPacket& recvPacket);
static void HandleAddFriendOpcodeCallBack(QueryResult_AutoPtr result, uint32 accountId, std::string friendNote);
void HandleAddFriendOpcodeCallBack(QueryResult_AutoPtr result, std::string friendNote);
void HandleDelFriendOpcode(WorldPacket& recvPacket);
void HandleAddIgnoreOpcode(WorldPacket& recvPacket);
static void HandleAddIgnoreOpcodeCallBack(QueryResult_AutoPtr result, uint32 accountId);
void HandleAddIgnoreOpcodeCallBack(QueryResult_AutoPtr result);
void HandleDelIgnoreOpcode(WorldPacket& recvPacket);
void HandleSetContactNotesOpcode(WorldPacket& recvPacket);
void HandleBugOpcode(WorldPacket& recvPacket);
@@ -665,7 +665,7 @@ class WorldSession
void HandleSetActionBarToggles(WorldPacket& recv_data);
void HandleCharRenameOpcode(WorldPacket& recv_data);
static void HandleChangePlayerNameOpcodeCallBack(QueryResult_AutoPtr result, uint32 accountId, std::string newname);
void HandleChangePlayerNameOpcodeCallBack(QueryResult_AutoPtr result, std::string newname);
void HandleSetPlayerDeclinedNames(WorldPacket& recv_data);
void HandleTotemDestroyed(WorldPacket& recv_data);
@@ -798,6 +798,17 @@ class WorldSession
void HandleQuestPOIQuery(WorldPacket& recv_data);
void HandleEjectPasenger(WorldPacket &data);
void HandleEnterPlayerVehicle(WorldPacket &data);
private:
void ProcessQueryCallbacks();
QueryResultFutureSet m_nameQueryCallbacks;
QueryResultFuture m_charEnumCallback;
QueryResultFuture m_addIgnoreCallback;
QueryCallback<std::string> m_charRenameCallback;
QueryCallback<std::string> m_addFriendCallback;
QueryResultHolderFuture m_charLoginCallback;
private:
// private trade methods
void moveItems(Item* myItems[], Item* hisItems[]);
+20 -19
View File
@@ -54,7 +54,6 @@
#include "VMapFactory.h"
#include "GameEventMgr.h"
#include "PoolMgr.h"
#include "AsyncDatabaseImpl.h"
#include "GridNotifiersImpl.h"
#include "CellImpl.h"
#include "InstanceSaveMgr.h"
@@ -103,7 +102,6 @@ World::World()
m_maxQueuedSessionCount = 0;
m_PlayerCount = 0;
m_MaxPlayerCount = 0;
m_resultQueue = NULL;
m_NextDailyQuestReset = 0;
m_NextWeeklyQuestReset = 0;
m_scheduledScripts = 0;
@@ -134,8 +132,6 @@ World::~World()
VMAP::VMapFactory::clear();
delete m_resultQueue;
//TODO free addSessQueue
}
@@ -1979,8 +1975,8 @@ void World::Update(uint32 diff)
RecordTimeDiff("UpdateLFGMgr");
// execute callbacks from sql queries that were queued recently
UpdateResultQueue();
RecordTimeDiff("UpdateResultQueue");
ProcessQueryCallbacks();
RecordTimeDiff("ProcessQueryCallbacks");
///- Erase corpses once every 20 minutes
if (m_timers[WUPDATE_CORPSES].Passed())
@@ -2500,21 +2496,12 @@ void World::SendRNDBroadcast()
}
}
void World::InitResultQueue()
{
m_resultQueue = new SQLResultQueue;
CharacterDatabase.SetResultQueue(m_resultQueue);
}
void World::UpdateResultQueue()
{
m_resultQueue->Update();
}
void World::UpdateRealmCharCount(uint32 accountId)
{
CharacterDatabase.AsyncPQuery(this, &World::_UpdateRealmCharCount, accountId,
"SELECT COUNT(guid) FROM characters WHERE account = '%u'", accountId);
m_realmCharCallback.SetParam(accountId);
m_realmCharCallback.SetFutureResult(
LoginDatabase.AsyncPQuery("SELECT COUNT(guid) FROM characters WHERE account = '%u'", accountId)
);
}
void World::_UpdateRealmCharCount(QueryResult_AutoPtr resultCharCount, uint32 accountId)
@@ -2742,3 +2729,17 @@ uint64 World::getWorldState(uint32 index) const
WorldStatesMap::const_iterator it = m_worldstates.find(index);
return it != m_worldstates.end() ? it->second : 0;
}
void World::ProcessQueryCallbacks()
{
QueryResult_AutoPtr result;
//-UpdateRealmCharCount
if (m_realmCharCallback.IsReady())
{
uint32 param = m_realmCharCallback.GetParam();
m_realmCharCallback.GetResult(result);
_UpdateRealmCharCount(result, param);
m_realmCharCallback.FreeResult();
}
}
+5 -5
View File
@@ -31,6 +31,7 @@
#include "SharedDefines.h"
#include "ace/Atomic_Op.h"
#include "QueryResult.h"
#include "Callback.h"
#include <map>
#include <set>
@@ -42,7 +43,6 @@ class WorldSession;
class Player;
struct ScriptAction;
struct ScriptInfo;
class SQLResultQueue;
class QueryResult;
class WorldSocket;
class SystemMgr;
@@ -670,9 +670,6 @@ class World
void ProcessCliCommands();
void QueueCliCommand(CliCommandHolder* commandHolder) { cliCmdQueue.add(commandHolder); }
void UpdateResultQueue();
void InitResultQueue();
void ForceGameEventUpdate();
void UpdateRealmCharCount(uint32 accid);
@@ -768,7 +765,6 @@ class World
// CLI command holder to be thread safe
ACE_Based::LockedQueue<CliCommandHolder*,ACE_Thread_Mutex> cliCmdQueue;
SQLResultQueue *m_resultQueue;
// next daily quests and random bg reset time
time_t m_NextDailyQuestReset;
@@ -787,6 +783,10 @@ class World
std::string m_CreatureEventAIVersion;
std::list<std::string> m_Autobroadcasts;
private:
void ProcessQueryCallbacks();
QueryCallback<uint32> m_realmCharCallback;
};
extern uint32 realmID;
@@ -1,250 +0,0 @@
/*
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
*
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "DatabaseWorkerPool.h"
#include "SQLOperation.h"
/// Function body definitions for the template function members of the Database class
#define ASYNC_QUERY_BODY(sql, queue_itr) \
if (!sql) return false; \
\
QueryQueues::iterator queue_itr; \
\
{ \
ACE_Based::Thread * queryThread = ACE_Based::Thread::current(); \
queue_itr = m_queryQueues.find(queryThread); \
if (queue_itr == m_queryQueues.end()) return false; \
}
#define ASYNC_PQUERY_BODY(format, szQuery) \
if(!format) return false; \
\
char szQuery [MAX_QUERY_LEN]; \
\
{ \
va_list ap; \
\
va_start(ap, format); \
int res = vsnprintf( szQuery, MAX_QUERY_LEN, format, ap ); \
va_end(ap); \
\
if(res==-1) \
{ \
sLog.outError("SQL Query truncated (and not execute) for format: %s",format); \
return false; \
} \
}
#define ASYNC_DELAYHOLDER_BODY(holder, queue_itr) \
if (!holder) return false; \
\
QueryQueues::iterator queue_itr; \
\
{ \
ACE_Based::Thread * queryThread = ACE_Based::Thread::current(); \
queue_itr = m_queryQueues.find(queryThread); \
if (queue_itr == m_queryQueues.end()) return false; \
}
// -- Query / member --
template<class Class>
bool
DatabaseWorkerPool::AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr), const char *sql)
{
ASYNC_QUERY_BODY(sql, itr)
SQLQueryTask* task = new SQLQueryTask(sql, new Trinity::QueryCallback<Class>(object, method), itr->second);
Enqueue(task);
return true;
}
template<class Class, typename ParamType1>
bool
DatabaseWorkerPool::AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *sql)
{
ASYNC_QUERY_BODY(sql, itr)
SQLQueryTask* task = new SQLQueryTask(sql, new Trinity::QueryCallback<Class, ParamType1>(object, method, (QueryResult_AutoPtr)NULL, param1), itr->second);
Enqueue(task);
return true;
}
template<class Class, typename ParamType1, typename ParamType2>
bool
DatabaseWorkerPool::AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *sql)
{
ASYNC_QUERY_BODY(sql, itr)
SQLQueryTask* task = new SQLQueryTask(sql, new Trinity::QueryCallback<Class, ParamType1, ParamType2>(object, method, (QueryResult_AutoPtr)NULL, param1, param2), itr->second);
Enqueue(task);
return true;
}
template<class Class, typename ParamType1, typename ParamType2, typename ParamType3>
bool
DatabaseWorkerPool::AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *sql)
{
ASYNC_QUERY_BODY(sql, itr)
SQLQueryTask* task = new SQLQueryTask(sql, new Trinity::QueryCallback<Class, ParamType1, ParamType2, ParamType3>(object, method, (QueryResult_AutoPtr)NULL, param1, param2, param3), itr->second);
Enqueue(task);
return true;
}
// -- Query / static --
template<typename ParamType1>
bool
DatabaseWorkerPool::AsyncQuery(void (*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *sql)
{
ASYNC_QUERY_BODY(sql, itr)
SQLQueryTask* task = new SQLQueryTask(sql, new Trinity::SQueryCallback<ParamType1>(method, (QueryResult_AutoPtr)NULL, param1), itr->second);
Enqueue(task);
return true;
}
template<typename ParamType1, typename ParamType2>
bool
DatabaseWorkerPool::AsyncQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *sql)
{
ASYNC_QUERY_BODY(sql, itr)
SQLQueryTask* task = new SQLQueryTask(sql, new Trinity::SQueryCallback<ParamType1, ParamType2>(method, (QueryResult_AutoPtr)NULL, param1, param2), itr->second);
Enqueue(task);
return true;
}
template<typename ParamType1, typename ParamType2, typename ParamType3>
bool
DatabaseWorkerPool::AsyncQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *sql)
{
ASYNC_QUERY_BODY(sql, itr)
SQLQueryTask* task = new SQLQueryTask(sql, new Trinity::SQueryCallback<ParamType1, ParamType2, ParamType3>(method, (QueryResult_AutoPtr)NULL, param1, param2, param3), itr->second);
Enqueue(task);
return true;
}
// -- PQuery / member --
template<class Class>
bool
DatabaseWorkerPool::AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr), const char *format,...)
{
ASYNC_PQUERY_BODY(format, szQuery)
return AsyncQuery(object, method, szQuery);
}
template<class Class, typename ParamType1>
bool
DatabaseWorkerPool::AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *format,...)
{
ASYNC_PQUERY_BODY(format, szQuery)
return AsyncQuery(object, method, param1, szQuery);
}
template<class Class, typename ParamType1, typename ParamType2>
bool
DatabaseWorkerPool::AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *format,...)
{
ASYNC_PQUERY_BODY(format, szQuery)
return AsyncQuery(object, method, param1, param2, szQuery);
}
template<class Class, typename ParamType1, typename ParamType2, typename ParamType3>
bool
DatabaseWorkerPool::AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *format,...)
{
ASYNC_PQUERY_BODY(format, szQuery)
return AsyncQuery(object, method, param1, param2, param3, szQuery);
}
// -- PQuery / static --
template<typename ParamType1>
bool
DatabaseWorkerPool::AsyncPQuery(void (*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *format,...)
{
ASYNC_PQUERY_BODY(format, szQuery)
return AsyncQuery(method, param1, szQuery);
}
template<typename ParamType1, typename ParamType2>
bool
DatabaseWorkerPool::AsyncPQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *format,...)
{
ASYNC_PQUERY_BODY(format, szQuery)
return AsyncQuery(method, param1, param2, szQuery);
}
template<typename ParamType1, typename ParamType2, typename ParamType3>
bool
DatabaseWorkerPool::AsyncPQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *format,...)
{
ASYNC_PQUERY_BODY(format, szQuery)
return AsyncQuery(method, param1, param2, param3, szQuery);
}
// -- QueryHolder --
template<class Class>
bool
DatabaseWorkerPool::DelayQueryHolder(Class *object, void (Class::*method)(QueryResult_AutoPtr, SQLQueryHolder*), SQLQueryHolder *holder)
{
ASYNC_DELAYHOLDER_BODY(holder, itr)
SQLQueryHolderTask *task = new SQLQueryHolderTask(holder, new Trinity::QueryCallback<Class, SQLQueryHolder*>(object, method, (QueryResult_AutoPtr)NULL, holder), itr->second);
Enqueue(task);
return true;
}
template<class Class, typename ParamType1>
bool
DatabaseWorkerPool::DelayQueryHolder(Class *object, void (Class::*method)(QueryResult_AutoPtr, SQLQueryHolder*, ParamType1), SQLQueryHolder *holder, ParamType1 param1)
{
ASYNC_DELAYHOLDER_BODY(holder, itr)
SQLQueryHolderTask *task = new SQLQueryHolderTask(holder, new Trinity::QueryCallback<Class, SQLQueryHolder*, ParamType1>(object, method, (QueryResult_AutoPtr)NULL, holder, param1), itr->second);
Enqueue(task);
return true;
}
#undef ASYNC_QUERY_BODY
#undef ASYNC_PQUERY_BODY
#undef ASYNC_DELAYHOLDER_BODY
@@ -197,6 +197,32 @@ void DatabaseWorkerPool::CommitTransaction()
}
}
QueryResultFuture DatabaseWorkerPool::AsyncQuery(const char* sql)
{
QueryResultFuture res;
BasicStatementTask* task = new BasicStatementTask(sql, res);
Enqueue(task);
return res; //! Fool compiler, has no use yet
}
QueryResultFuture DatabaseWorkerPool::AsyncPQuery(const char* sql, ...)
{
va_list ap;
char szQuery[MAX_QUERY_LEN];
va_start(ap, sql);
int res = vsnprintf(szQuery, MAX_QUERY_LEN, sql, ap);
va_end(ap);
return AsyncQuery(szQuery);
}
QueryResultHolderFuture DatabaseWorkerPool::DelayQueryHolder(SQLQueryHolder* holder)
{
QueryResultHolderFuture res;
SQLQueryHolderTask* task = new SQLQueryHolderTask(holder, res);
Enqueue(task);
return res; //! Fool compiler, has no use yet
}
MySQLConnection* DatabaseWorkerPool::GetConnection()
{
@@ -26,6 +26,7 @@
#include "SQLOperation.h"
#include "QueryResult.h"
#include "Callback.h"
#include "MySQLConnection.h"
enum MySQLThreadBundle
@@ -56,51 +57,9 @@ class DatabaseWorkerPool
void DirectPExecute(const char* sql, ...);
QueryResult_AutoPtr Query(const char* sql);
QueryResult_AutoPtr PQuery(const char* sql, ...);
/// Async queries and query holders, implemented in DatabaseImpl.h
// Query / member
template<class Class>
bool AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr), const char *sql);
template<class Class, typename ParamType1>
bool AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *sql);
template<class Class, typename ParamType1, typename ParamType2>
bool AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *sql);
template<class Class, typename ParamType1, typename ParamType2, typename ParamType3>
bool AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *sql);
// Query / static
template<typename ParamType1>
bool AsyncQuery(void (*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *sql);
template<typename ParamType1, typename ParamType2>
bool AsyncQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *sql);
template<typename ParamType1, typename ParamType2, typename ParamType3>
bool AsyncQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *sql);
// PQuery / member
template<class Class>
bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr), const char *format,...) ATTR_PRINTF(4,5);
template<class Class, typename ParamType1>
bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *format,...) ATTR_PRINTF(5,6);
template<class Class, typename ParamType1, typename ParamType2>
bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *format,...) ATTR_PRINTF(6,7);
template<class Class, typename ParamType1, typename ParamType2, typename ParamType3>
bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *format,...) ATTR_PRINTF(7,8);
// PQuery / static
template<typename ParamType1>
bool AsyncPQuery(void (*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *format,...) ATTR_PRINTF(4,5);
template<typename ParamType1, typename ParamType2>
bool AsyncPQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *format,...) ATTR_PRINTF(5,6);
template<typename ParamType1, typename ParamType2, typename ParamType3>
bool AsyncPQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *format,...) ATTR_PRINTF(6,7);
template<class Class>
// QueryHolder
bool DelayQueryHolder(Class *object, void (Class::*method)(QueryResult_AutoPtr, SQLQueryHolder*), SQLQueryHolder *holder);
template<class Class, typename ParamType1>
bool DelayQueryHolder(Class *object, void (Class::*method)(QueryResult_AutoPtr, SQLQueryHolder*, ParamType1), SQLQueryHolder *holder, ParamType1 param1);
void SetResultQueue(SQLResultQueue * queue)
{
m_queryQueues[ACE_Based::Thread::current()] = queue;
}
QueryResultFuture AsyncQuery(const char* sql);
QueryResultFuture AsyncPQuery(const char* sql, ...);
QueryResultHolderFuture DelayQueryHolder(SQLQueryHolder* holder);
void BeginTransaction();
void RollbackTransaction();
@@ -135,7 +94,6 @@ class DatabaseWorkerPool
private:
typedef UNORDERED_MAP<ACE_Based::Thread*, MySQLConnection*> ConnectionMap;
typedef UNORDERED_MAP<ACE_Based::Thread*, TransactionTask*> TransactionQueues;
typedef UNORDERED_MAP<ACE_Based::Thread*, SQLResultQueue*> QueryQueues;
typedef ACE_Atomic_Op<ACE_SYNCH_MUTEX, uint32> AtomicUInt;
private:
@@ -149,7 +107,6 @@ class DatabaseWorkerPool
std::string m_infoString; //! Infostring that is passed on to child connections.
TransactionQueues m_tranQueues; //! Transaction queues from diff. threads
ACE_Thread_Mutex m_transQueues_mtx; //! To guard m_transQueues
QueryQueues m_queryQueues; //! Query queues from diff threads
};
#endif
+20 -28
View File
@@ -21,7 +21,15 @@
#include "Log.h"
/*! Basic, ad-hoc queries. */
BasicStatementTask::BasicStatementTask(const char* sql)
BasicStatementTask::BasicStatementTask(const char* sql) :
m_has_result(false)
{
m_sql = strdup(sql);
}
BasicStatementTask::BasicStatementTask(const char* sql, QueryResultFuture result) :
m_result(result),
m_has_result(true)
{
m_sql = strdup(sql);
}
@@ -33,6 +41,15 @@ BasicStatementTask::~BasicStatementTask()
bool BasicStatementTask::Execute()
{
if (m_has_result)
{
m_result.set(
m_conn->Query(m_sql)
);
return true;
}
return m_conn->Execute(m_sql);
}
@@ -83,18 +100,6 @@ bool TransactionTask::Execute()
return true;
}
/*! Callback statements/holders */
void SQLResultQueue::Update()
{
/// execute the callbacks waiting in the synchronization queue
Trinity::IQueryCallback* callback;
while (next(callback))
{
callback->Execute();
delete callback;
}
}
bool SQLQueryHolder::SetQuery(size_t index, const char *sql)
{
if (m_queries.size() <= index)
@@ -181,7 +186,7 @@ void SQLQueryHolder::SetSize(size_t size)
bool SQLQueryHolderTask::Execute()
{
if (!m_holder || !m_callback || !m_queue)
if (!m_holder)
return false;
/// we can do this, we are friends
@@ -195,19 +200,6 @@ bool SQLQueryHolderTask::Execute()
m_holder->SetResult(i, m_conn->Query(sql));
}
/// sync with the caller thread
m_queue->add(m_callback);
return true;
}
bool SQLQueryTask::Execute()
{
if (!m_callback || !m_queue)
return false;
/// execute the query and store the result in the callback
m_callback->SetResult(m_conn->Query(m_sql));
/// add the callback to the sql result queue of the thread it originated from
m_queue->add(m_callback);
m_result.set(m_holder);
return true;
}
+9 -24
View File
@@ -43,17 +43,21 @@ class SQLOperation : public ACE_Method_Request
MySQLConnection* m_conn;
};
typedef ACE_Future<QueryResult_AutoPtr> QueryResultFuture;
/*! Raw, ad-hoc query. */
class BasicStatementTask : public SQLOperation
{
public:
BasicStatementTask(const char* sql);
BasicStatementTask(const char* sql, QueryResultFuture result);
~BasicStatementTask();
bool Execute();
private:
const char* m_sql; //- Raw query to be executed
bool m_has_result;
QueryResultFuture m_result;
};
/*! Transactions */
@@ -70,14 +74,6 @@ class TransactionTask : public SQLOperation
std::queue<char*> m_queries;
};
/*! ResultQueue */
class SQLResultQueue : public ACE_Based::LockedQueue<Trinity::IQueryCallback* , ACE_Thread_Mutex>
{
public:
SQLResultQueue() {}
void Update();
};
class SQLQueryHolder
{
friend class SQLQueryHolderTask;
@@ -94,28 +90,17 @@ class SQLQueryHolder
void SetResult(size_t index, QueryResult_AutoPtr result);
};
typedef ACE_Future<SQLQueryHolder*> QueryResultHolderFuture;
class SQLQueryHolderTask : public SQLOperation
{
private:
SQLQueryHolder * m_holder;
Trinity::IQueryCallback * m_callback;
SQLResultQueue * m_queue;
public:
SQLQueryHolderTask(SQLQueryHolder *holder, Trinity::IQueryCallback * callback, SQLResultQueue * queue)
: m_holder(holder), m_callback(callback), m_queue(queue) {}
bool Execute();
};
QueryResultHolderFuture m_result;
class SQLQueryTask : public SQLOperation
{
private:
const char *m_sql;
Trinity::IQueryCallback * m_callback;
SQLResultQueue * m_queue;
public:
SQLQueryTask(const char *sql, Trinity::IQueryCallback * callback, SQLResultQueue * queue)
: m_sql(strdup(sql)), m_callback(callback), m_queue(queue) {}
~SQLQueryTask() { void* tofree = const_cast<char*>(m_sql); free(tofree); }
SQLQueryHolderTask(SQLQueryHolder *holder, QueryResultHolderFuture res)
: m_holder(holder), m_result(res){};
bool Execute();
};
+50 -353
View File
@@ -1,6 +1,4 @@
/*
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
*
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify
@@ -18,369 +16,68 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef TRINITY_CALLBACK_H
#define TRINITY_CALLBACK_H
#ifndef _CALLBACK_H
#define _CALLBACK_H
/// ------------ BASE CLASSES ------------
#include <ace/Future.h>
#include <ace/Future_Set.h>
namespace Trinity
#include "DatabaseEnv.h"
typedef ACE_Future<QueryResult_AutoPtr> QueryResultFuture;
/*! A simple template using ACE_Future to manage callbacks from the thread and object that
issued the request. <ParamType> is variable type of parameter that is used as parameter
for the callback function.
*/
template <typename ParamType>
class QueryCallback
{
template < class Class, typename ParamType1 = void, typename ParamType2 = void, typename ParamType3 = void, typename ParamType4 = void >
class _Callback
{
protected:
typedef void (Class::*Method)(ParamType1, ParamType2, ParamType3, ParamType4);
Class *m_object;
Method m_method;
ParamType1 m_param1;
ParamType2 m_param2;
ParamType3 m_param3;
ParamType4 m_param4;
void _Execute() { (m_object->*m_method)(m_param1, m_param2, m_param3, m_param4); }
public:
_Callback(Class *object, Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3, ParamType4 param4)
: m_object(object), m_method(method), m_param1(param1), m_param2(param2), m_param3(param3), m_param4(param4) {}
_Callback(_Callback < Class, ParamType1, ParamType2, ParamType3, ParamType4> const& cb)
: m_object(cb.object), m_method(cb.m_method), m_param1(cb.m_param1), m_param2(cb.m_param2), m_param3(cb.m_param3), m_param4(cb.m_param4) {}
};
QueryCallback() {}
template < class Class, typename ParamType1, typename ParamType2, typename ParamType3 >
class _Callback < Class, ParamType1, ParamType2, ParamType3 >
void SetFutureResult(QueryResultFuture value)
{
protected:
typedef void (Class::*Method)(ParamType1, ParamType2, ParamType3);
Class *m_object;
Method m_method;
ParamType1 m_param1;
ParamType2 m_param2;
ParamType3 m_param3;
void _Execute() { (m_object->*m_method)(m_param1, m_param2, m_param3); }
public:
_Callback(Class *object, Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3)
: m_object(object), m_method(method), m_param1(param1), m_param2(param2) {}
_Callback(_Callback < Class, ParamType1, ParamType2, ParamType3 > const& cb)
: m_object(cb.object), m_method(cb.m_method), m_param1(cb.m_param1), m_param2(cb.m_param2), m_param3(cb.m_param3) {}
};
template < class Class, typename ParamType1, typename ParamType2 >
class _Callback < Class, ParamType1, ParamType2 >
{
protected:
typedef void (Class::*Method)(ParamType1, ParamType2);
Class *m_object;
Method m_method;
ParamType1 m_param1;
ParamType2 m_param2;
void _Execute() { (m_object->*m_method)(m_param1, m_param2); }
public:
_Callback(Class *object, Method method, ParamType1 param1, ParamType2 param2)
: m_object(object), m_method(method), m_param1(param1), m_param2(param2) {}
_Callback(_Callback < Class, ParamType1, ParamType2 > const& cb)
: m_object(cb.m_object), m_method(cb.m_method), m_param1(cb.m_param1), m_param2(cb.m_param2) {}
};
template < class Class, typename ParamType1 >
class _Callback < Class, ParamType1 >
{
protected:
typedef void (Class::*Method)(ParamType1);
Class *m_object;
Method m_method;
ParamType1 m_param1;
void _Execute() { (m_object->*m_method)(m_param1); }
public:
_Callback(Class *object, Method method, ParamType1 param1)
: m_object(object), m_method(method), m_param1(param1) {}
_Callback(_Callback < Class, ParamType1 > const& cb)
: m_object(cb.m_object), m_method(cb.m_method), m_param1(cb.m_param1) {}
};
template < class Class >
class _Callback < Class >
{
protected:
typedef void (Class::*Method)();
Class *m_object;
Method m_method;
void _Execute() { (m_object->*m_method)(); }
public:
_Callback(Class *object, Method method)
: m_object(object), m_method(method) {}
_Callback(_Callback < Class > const& cb)
: m_object(cb.m_object), m_method(cb.m_method) {}
};
/// ---- Statics ----
template < typename ParamType1 = void, typename ParamType2 = void, typename ParamType3 = void, typename ParamType4 = void >
class _SCallback
{
protected:
typedef void (*Method)(ParamType1, ParamType2, ParamType3, ParamType4);
Method m_method;
ParamType1 m_param1;
ParamType2 m_param2;
ParamType3 m_param3;
ParamType4 m_param4;
void _Execute() { (*m_method)(m_param1, m_param2, m_param3, m_param4); }
public:
_SCallback(Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3, ParamType4 param4)
: m_method(method), m_param1(param1), m_param2(param2), m_param3(param3), m_param4(param4) {}
_SCallback(_SCallback < ParamType1, ParamType2, ParamType3, ParamType4> const& cb)
: m_method(cb.m_method), m_param1(cb.m_param1), m_param2(cb.m_param2), m_param3(cb.m_param3), m_param4(cb.m_param4) {}
};
template < typename ParamType1, typename ParamType2, typename ParamType3 >
class _SCallback < ParamType1, ParamType2, ParamType3 >
{
protected:
typedef void (*Method)(ParamType1, ParamType2, ParamType3);
Method m_method;
ParamType1 m_param1;
ParamType2 m_param2;
ParamType3 m_param3;
void _Execute() { (*m_method)(m_param1, m_param2, m_param3); }
public:
_SCallback(Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3)
: m_method(method), m_param1(param1), m_param2(param2), m_param3(param3) {}
_SCallback(_SCallback < ParamType1, ParamType2, ParamType3 > const& cb)
: m_method(cb.m_method), m_param1(cb.m_param1), m_param2(cb.m_param2), m_param3(cb.m_param3) {}
};
template < typename ParamType1, typename ParamType2 >
class _SCallback < ParamType1, ParamType2 >
{
protected:
typedef void (*Method)(ParamType1, ParamType2);
Method m_method;
ParamType1 m_param1;
ParamType2 m_param2;
void _Execute() { (*m_method)(m_param1, m_param2); }
public:
_SCallback(Method method, ParamType1 param1, ParamType2 param2)
: m_method(method), m_param1(param1), m_param2(param2) {}
_SCallback(_SCallback < ParamType1, ParamType2 > const& cb)
: m_method(cb.m_method), m_param1(cb.m_param1), m_param2(cb.m_param2) {}
};
template < typename ParamType1 >
class _SCallback < ParamType1 >
{
protected:
typedef void (*Method)(ParamType1);
Method m_method;
ParamType1 m_param1;
void _Execute() { (*m_method)(m_param1); }
public:
_SCallback(Method method, ParamType1 param1)
: m_method(method), m_param1(param1) {}
_SCallback(_SCallback < ParamType1 > const& cb)
: m_method(cb.m_method), m_param1(cb.m_param1) {}
};
template < >
class _SCallback < >
{
protected:
typedef void (*Method)();
Method m_method;
void _Execute() { (*m_method)(); }
public:
_SCallback(Method method)
: m_method(method) {}
_SCallback(_SCallback <> const& cb)
: m_method(cb.m_method) {}
};
result = value;
}
/// --------- GENERIC CALLBACKS ----------
namespace Trinity
QueryResultFuture GetFutureResult()
{
class ICallback
{
public:
virtual void Execute() = 0;
virtual ~ICallback() {}
};
template < class CB >
class _ICallback : public CB, public ICallback
{
public:
_ICallback(CB const& cb) : CB(cb) {}
void Execute() { CB::_Execute(); }
};
template < class Class, typename ParamType1 = void, typename ParamType2 = void, typename ParamType3 = void, typename ParamType4 = void >
class Callback :
public _ICallback< _Callback < Class, ParamType1, ParamType2, ParamType3, ParamType4 > >
{
private:
typedef _Callback < Class, ParamType1, ParamType2, ParamType3, ParamType4 > C4;
public:
Callback(Class *object, typename C4::Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3, ParamType4 param4)
: _ICallback< C4 >(C4(object, method, param1, param2, param3, param4)) {}
};
template < class Class, typename ParamType1, typename ParamType2, typename ParamType3 >
class Callback < Class, ParamType1, ParamType2, ParamType3 > :
public _ICallback< _Callback < Class, ParamType1, ParamType2, ParamType3 > >
{
private:
typedef _Callback < Class, ParamType1, ParamType2, ParamType3 > C3;
public:
Callback(Class *object, typename C3::Method method, ParamType1 param1, ParamType2 param2, ParamType3 param3)
: _ICallback< C3 >(C3(object, method, param1, param2, param3)) {}
};
template < class Class, typename ParamType1, typename ParamType2 >
class Callback < Class, ParamType1, ParamType2 > :
public _ICallback< _Callback < Class, ParamType1, ParamType2 > >
{
private:
typedef _Callback < Class, ParamType1, ParamType2 > C2;
public:
Callback(Class *object, typename C2::Method method, ParamType1 param1, ParamType2 param2)
: _ICallback< C2 >(C2(object, method, param1, param2)) {}
};
template < class Class, typename ParamType1 >
class Callback < Class, ParamType1 > :
public _ICallback< _Callback < Class, ParamType1 > >
{
private:
typedef _Callback < Class, ParamType1 > C1;
public:
Callback(Class *object, typename C1::Method method, ParamType1 param1)
: _ICallback< C1 >(C1(object, method, param1)) {}
};
template < class Class >
class Callback < Class > : public _ICallback< _Callback < Class > >
{
private:
typedef _Callback < Class > C0;
public:
Callback(Class *object, typename C0::Method method)
: _ICallback< C0 >(C0(object, method)) {}
};
return result;
}
/// ---------- QUERY CALLBACKS -----------
#include "QueryResult.h"
class QueryResult;
namespace Trinity
int IsReady()
{
class IQueryCallback
{
public:
virtual void Execute() = 0;
virtual ~IQueryCallback() {}
virtual void SetResult(QueryResult_AutoPtr result) = 0;
virtual QueryResult_AutoPtr GetResult() = 0;
};
template < class CB >
class _IQueryCallback : public CB, public IQueryCallback
{
public:
_IQueryCallback(CB const& cb) : CB(cb) {}
void Execute() { CB::_Execute(); }
void SetResult(QueryResult_AutoPtr result) { CB::m_param1 = result; }
QueryResult_AutoPtr GetResult() { return CB::m_param1; }
};
template < class Class, typename ParamType1 = void, typename ParamType2 = void, typename ParamType3 = void >
class QueryCallback :
public _IQueryCallback< _Callback < Class, QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3 > >
{
private:
typedef _Callback < Class, QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3 > QC3;
public:
QueryCallback(Class *object, typename QC3::Method method, QueryResult_AutoPtr result, ParamType1 param1, ParamType2 param2, ParamType3 param3)
: _IQueryCallback< QC3 >(QC3(object, method, result, param1, param2, param3)) {}
};
template < class Class, typename ParamType1, typename ParamType2 >
class QueryCallback < Class, ParamType1, ParamType2 > :
public _IQueryCallback< _Callback < Class, QueryResult_AutoPtr, ParamType1, ParamType2 > >
{
private:
typedef _Callback < Class, QueryResult_AutoPtr, ParamType1, ParamType2 > QC2;
public:
QueryCallback(Class *object, typename QC2::Method method, QueryResult_AutoPtr result, ParamType1 param1, ParamType2 param2)
: _IQueryCallback< QC2 >(QC2(object, method, result, param1, param2)) {}
};
template < class Class, typename ParamType1 >
class QueryCallback < Class, ParamType1 > :
public _IQueryCallback< _Callback < Class, QueryResult_AutoPtr, ParamType1 > >
{
private:
typedef _Callback < Class, QueryResult_AutoPtr, ParamType1 > QC1;
public:
QueryCallback(Class *object, typename QC1::Method method, QueryResult_AutoPtr result, ParamType1 param1)
: _IQueryCallback< QC1 >(QC1(object, method, result, param1)) {}
};
template < class Class >
class QueryCallback < Class > : public _IQueryCallback< _Callback < Class, QueryResult_AutoPtr > >
{
private:
typedef _Callback < Class, QueryResult_AutoPtr > QC0;
public:
QueryCallback(Class *object, typename QC0::Method method, QueryResult_AutoPtr result)
: _IQueryCallback< QC0 >(QC0(object, method, result)) {}
};
/// ---- Statics ----
template < typename ParamType1 = void, typename ParamType2 = void, typename ParamType3 = void >
class SQueryCallback :
public _IQueryCallback< _SCallback < QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3 > >
{
private:
typedef _SCallback < QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3 > QC3;
public:
SQueryCallback(typename QC3::Method method, QueryResult_AutoPtr result, ParamType1 param1, ParamType2 param2, ParamType3 param3)
: _IQueryCallback< QC3 >(QC3(method, result, param1, param2, param3)) {}
};
template < typename ParamType1, typename ParamType2 >
class SQueryCallback < ParamType1, ParamType2 > :
public _IQueryCallback< _SCallback < QueryResult_AutoPtr, ParamType1, ParamType2 > >
{
private:
typedef _SCallback < QueryResult_AutoPtr, ParamType1, ParamType2 > QC2;
public:
SQueryCallback(typename QC2::Method method, QueryResult_AutoPtr result, ParamType1 param1, ParamType2 param2)
: _IQueryCallback< QC2 >(QC2(method, result, param1, param2)) {}
};
template < typename ParamType1 >
class SQueryCallback < ParamType1 > :
public _IQueryCallback< _SCallback < QueryResult_AutoPtr, ParamType1 > >
{
private:
typedef _SCallback < QueryResult_AutoPtr, ParamType1 > QC1;
public:
SQueryCallback(typename QC1::Method method, QueryResult_AutoPtr result, ParamType1 param1)
: _IQueryCallback< QC1 >(QC1(method, result, param1)) {}
};
template < >
class SQueryCallback < > : public _IQueryCallback< _SCallback < QueryResult_AutoPtr > >
{
private:
typedef _SCallback < QueryResult_AutoPtr > QC0;
public:
SQueryCallback(QC0::Method method, QueryResult_AutoPtr result)
: _IQueryCallback< QC0 >(QC0(method, result)) {}
};
return result.ready();
}
void GetResult(QueryResult_AutoPtr res)
{
result.get(res);
}
void FreeResult()
{
result.cancel();
}
void SetParam(ParamType value)
{
param = value;
}
ParamType GetParam()
{
return param;
}
private:
QueryResultFuture result;
ParamType param;
};
/*! ACE_Future_Set to store a bunch of unique async queries with callbacks.
(ie name queries)
*/
typedef ACE_Future_Set<QueryResult_AutoPtr> QueryResultFutureSet;
#endif
@@ -65,8 +65,6 @@ void WorldRunnable::run()
if (needInit)
MySQL::Thread_Init();
sWorld.InitResultQueue();
uint32 realCurrTime = 0;
uint32 realPrevTime = getMSTime();