aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/database/Database/QueryCallback.cpp120
-rw-r--r--src/server/database/Database/QueryCallback.h36
-rw-r--r--src/server/database/Database/QueryCallbackProcessor.h3
3 files changed, 100 insertions, 59 deletions
diff --git a/src/server/database/Database/QueryCallback.cpp b/src/server/database/Database/QueryCallback.cpp
index 92bb80a0b60..b77036b8e6a 100644
--- a/src/server/database/Database/QueryCallback.cpp
+++ b/src/server/database/Database/QueryCallback.cpp
@@ -17,6 +17,58 @@
#include "QueryCallback.h"
+template<typename T>
+inline void Destroy(T& t)
+{
+ t.~T();
+}
+
+template<typename T>
+void DestroyActiveMember(T& obj)
+{
+ if (!obj._isPrepared)
+ Destroy(obj._string);
+ else
+ Destroy(obj._prepared);
+}
+
+template<typename T>
+void MoveFrom(T& to, T&& from)
+{
+ DestroyActiveMember(to);
+ to._isPrepared = from._isPrepared;
+ if (!to._isPrepared)
+ to._string = std::move(from._string);
+ else
+ to._prepared = std::move(from._prepared);
+}
+
+struct QueryCallbackNew::QueryCallbackData
+{
+public:
+ friend class QueryCallbackNew;
+
+ QueryCallbackData(std::function<void(QueryResult)>&& callback) : _string(std::move(callback)), _isPrepared(false) { }
+ QueryCallbackData(std::function<void(PreparedQueryResult)>&& callback) : _prepared(std::move(callback)), _isPrepared(true) { }
+ QueryCallbackData(QueryCallbackData&& right) { MoveFrom(*this, std::move(right)); }
+ QueryCallbackData& operator=(QueryCallbackData&& right) { MoveFrom(*this, std::move(right)); }
+ ~QueryCallbackData() { DestroyActiveMember(*this); }
+
+private:
+ QueryCallbackData(QueryCallbackData const&) = delete;
+ QueryCallbackData& operator=(QueryCallbackData const&) = delete;
+
+ template<typename T> friend void MoveFrom(T& to, T&& from);
+ template<typename T> friend void DestroyActiveMember(T& obj);
+
+ union
+ {
+ std::function<void(QueryResult)> _string;
+ std::function<void(PreparedQueryResult)> _prepared;
+ };
+ bool _isPrepared;
+};
+
QueryCallbackNew::QueryCallbackNew(std::future<QueryResult>&& result) : _string(std::move(result)), _isPrepared(false)
{
}
@@ -27,72 +79,74 @@ QueryCallbackNew::QueryCallbackNew(std::future<PreparedQueryResult>&& result) :
QueryCallbackNew::QueryCallbackNew(QueryCallbackNew&& right)
{
- MoveFrom(std::move(right));
+ MoveFrom(*this, std::move(right));
+ _callbacks = std::move(right._callbacks);
}
QueryCallbackNew& QueryCallbackNew::operator=(QueryCallbackNew&& right)
{
- MoveFrom(std::move(right));
+ MoveFrom(*this, std::move(right));
+ _callbacks = std::move(right._callbacks);
return *this;
}
QueryCallbackNew::~QueryCallbackNew()
{
- DestroyCurrentMember();
+ DestroyActiveMember(*this);
}
QueryCallbackNew&& QueryCallbackNew::WithCallback(std::function<void(QueryResult)>&& callback)
{
- ASSERT(!_isPrepared, "Attempted to set callback function for string query on a prepared async query");
- _string.Callback = std::move(callback);
+ ASSERT(!_callbacks.empty() || !_isPrepared, "Attempted to set callback function for string query on a prepared async query");
+ _callbacks.emplace(std::move(callback));
return std::move(*this);
}
QueryCallbackNew&& QueryCallbackNew::WithPreparedCallback(std::function<void(PreparedQueryResult)>&& callback)
{
- ASSERT(_isPrepared, "Attempted to set callback function for prepared query on a string async query");
- _prepared.Callback = std::move(callback);
+ ASSERT(!_callbacks.empty() || _isPrepared, "Attempted to set callback function for prepared query on a string async query");
+ _callbacks.emplace(std::move(callback));
return std::move(*this);
}
QueryCallbackNew::Status QueryCallbackNew::InvokeIfReady()
{
+ QueryCallbackData& callback = _callbacks.front();
if (!_isPrepared)
{
- if (_string.Result.valid() && _string.Result.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
+ if (_string.valid() && _string.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
{
- std::function<void(QueryResult)> cb(std::move(_string.Callback));
- cb(_string.Result.get());
- return !_string.Callback ? Completed : NextStep;
+ std::function<void(QueryResult)> cb(std::move(callback._string));
+ cb(_string.get());
+ _callbacks.pop();
+ if (_callbacks.empty())
+ {
+ ASSERT(!_isPrepared ? !_string.valid() : !_prepared.valid());
+ return Completed;
+ }
+
+ ASSERT(_isPrepared == _callbacks.front()._isPrepared);
+ return NextStep;
}
}
else
{
- if (_prepared.Result.valid() && _prepared.Result.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
+ if (_prepared.valid() && _prepared.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
{
- std::function<void(PreparedQueryResult)> cb(std::move(_prepared.Callback));
- cb(_prepared.Result.get());
- return !_prepared.Callback ? Completed : NextStep;
+ std::future<PreparedQueryResult> f(std::move(_prepared));
+ std::function<void(PreparedQueryResult)> cb(std::move(callback._prepared));
+ cb(_prepared.get());
+ _callbacks.pop();
+ if (_callbacks.empty())
+ {
+ ASSERT(!_isPrepared ? !_string.valid() : !_prepared.valid());
+ return Completed;
+ }
+
+ ASSERT(_isPrepared == _callbacks.front()._isPrepared);
+ return NextStep;
}
}
return NotReady;
}
-
-void QueryCallbackNew::MoveFrom(QueryCallbackNew&& other)
-{
- DestroyCurrentMember();
- _isPrepared = other._isPrepared;
- if (!_isPrepared)
- _string = std::move(other._string);
- else
- _prepared = std::move(other._prepared);
-}
-
-void QueryCallbackNew::DestroyCurrentMember()
-{
- if (!_isPrepared)
- _string.~String();
- else
- _prepared.~Prepared();
-}
diff --git a/src/server/database/Database/QueryCallback.h b/src/server/database/Database/QueryCallback.h
index a0aa69ee952..6c4a8a81b4e 100644
--- a/src/server/database/Database/QueryCallback.h
+++ b/src/server/database/Database/QueryCallback.h
@@ -30,28 +30,6 @@ typedef std::promise<PreparedQueryResult> PreparedQueryResultPromise;
class TC_DATABASE_API QueryCallbackNew
{
- struct String
- {
- explicit String(std::future<QueryResult>&& result) : Result(std::move(result)) { }
- String(String&&) = default;
- String& operator=(String&&) = default;
- ~String() { }
-
- std::future<QueryResult> Result;
- std::function<void(QueryResult)> Callback;
- };
-
- struct Prepared
- {
- explicit Prepared(std::future<PreparedQueryResult>&& result) : Result(std::move(result)) { }
- Prepared(Prepared&&) = default;
- Prepared& operator=(Prepared&&) = default;
- ~Prepared() { }
-
- std::future<PreparedQueryResult> Result;
- std::function<void(PreparedQueryResult)> Callback;
- };
-
public:
explicit QueryCallbackNew(std::future<QueryResult>&& result);
explicit QueryCallbackNew(std::future<PreparedQueryResult>&& result);
@@ -72,15 +50,21 @@ public:
Status InvokeIfReady();
private:
- void MoveFrom(QueryCallbackNew&& other);
- void DestroyCurrentMember();
+ QueryCallbackNew(QueryCallbackNew const& right) = delete;
+ QueryCallbackNew& operator=(QueryCallbackNew const& right) = delete;
+
+ template<typename T> friend void MoveFrom(T& to, T&& from);
+ template<typename T> friend void DestroyActiveMember(T& obj);
union
{
- String _string;
- Prepared _prepared;
+ std::future<QueryResult> _string;
+ std::future<PreparedQueryResult> _prepared;
};
bool _isPrepared;
+
+ struct QueryCallbackData;
+ std::queue<QueryCallbackData, std::list<QueryCallbackData>> _callbacks;
};
template <typename Result, typename ParamType, bool chain = false>
diff --git a/src/server/database/Database/QueryCallbackProcessor.h b/src/server/database/Database/QueryCallbackProcessor.h
index a570a3fc1b9..08ae3d15693 100644
--- a/src/server/database/Database/QueryCallbackProcessor.h
+++ b/src/server/database/Database/QueryCallbackProcessor.h
@@ -33,6 +33,9 @@ public:
void ProcessReadyQueries();
private:
+ QueryCallbackProcessor(QueryCallbackProcessor const&) = delete;
+ QueryCallbackProcessor& operator=(QueryCallbackProcessor const&) = delete;
+
std::vector<QueryCallbackNew> _callbacks;
};