diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/database/Database/QueryCallback.cpp | 120 | ||||
-rw-r--r-- | src/server/database/Database/QueryCallback.h | 36 | ||||
-rw-r--r-- | src/server/database/Database/QueryCallbackProcessor.h | 3 |
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; }; |