TrinityCore
QueryCallback.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "QueryCallback.h"
19#include "Errors.h"
20
21template<typename T, typename... Args>
22inline void Construct(T& t, Args&&... args)
23{
24 new (&t) T(std::forward<Args>(args)...);
25}
26
27template<typename T>
28inline void Destroy(T& t)
29{
30 t.~T();
31}
32
33template<typename T>
34inline void ConstructActiveMember(T* obj)
35{
36 if (!obj->_isPrepared)
37 Construct(obj->_string);
38 else
39 Construct(obj->_prepared);
40}
41
42template<typename T>
43inline void DestroyActiveMember(T* obj)
44{
45 if (!obj->_isPrepared)
46 Destroy(obj->_string);
47 else
48 Destroy(obj->_prepared);
49}
50
51template<typename T>
52inline void MoveFrom(T* to, T&& from)
53{
54 ASSERT(to->_isPrepared == from._isPrepared);
55
56 if (!to->_isPrepared)
57 to->_string = std::move(from._string);
58 else
59 to->_prepared = std::move(from._prepared);
60}
61
63{
64public:
65 friend class QueryCallback;
66
67 QueryCallbackData(std::function<void(QueryCallback&, QueryResult)>&& callback) : _string(std::move(callback)), _isPrepared(false) { }
68 QueryCallbackData(std::function<void(QueryCallback&, PreparedQueryResult)>&& callback) : _prepared(std::move(callback)), _isPrepared(true) { }
70 {
71 _isPrepared = right._isPrepared;
73 MoveFrom(this, std::move(right));
74 }
76 {
77 if (this != &right)
78 {
79 if (_isPrepared != right._isPrepared)
80 {
82 _isPrepared = right._isPrepared;
84 }
85 MoveFrom(this, std::move(right));
86 }
87 return *this;
88 }
90
91private:
94
95 template<typename T> friend void ConstructActiveMember(T* obj);
96 template<typename T> friend void DestroyActiveMember(T* obj);
97 template<typename T> friend void MoveFrom(T* to, T&& from);
98
99 union
100 {
101 std::function<void(QueryCallback&, QueryResult)> _string;
103 };
105};
106
107// Not using initialization lists to work around segmentation faults when compiling with clang without precompiled headers
108QueryCallback::QueryCallback(std::future<QueryResult>&& result)
109{
110 _isPrepared = false;
111 Construct(_string, std::move(result));
112}
113
114QueryCallback::QueryCallback(std::future<PreparedQueryResult>&& result)
115{
116 _isPrepared = true;
117 Construct(_prepared, std::move(result));
118}
119
121{
122 _isPrepared = right._isPrepared;
124 MoveFrom(this, std::move(right));
125 _callbacks = std::move(right._callbacks);
126}
127
129{
130 if (this != &right)
131 {
132 if (_isPrepared != right._isPrepared)
133 {
135 _isPrepared = right._isPrepared;
137 }
138 MoveFrom(this, std::move(right));
139 _callbacks = std::move(right._callbacks);
140 }
141 return *this;
142}
143
145{
147}
148
149QueryCallback&& QueryCallback::WithCallback(std::function<void(QueryResult)>&& callback)
150{
151 return WithChainingCallback([callback](QueryCallback& /*this*/, QueryResult result) { callback(std::move(result)); });
152}
153
155{
156 return WithChainingPreparedCallback([callback](QueryCallback& /*this*/, PreparedQueryResult result) { callback(std::move(result)); });
157}
158
160{
161 ASSERT(!_callbacks.empty() || !_isPrepared, "Attempted to set callback function for string query on a prepared async query");
162 _callbacks.emplace(std::move(callback));
163 return std::move(*this);
164}
165
167{
168 ASSERT(!_callbacks.empty() || _isPrepared, "Attempted to set callback function for prepared query on a string async query");
169 _callbacks.emplace(std::move(callback));
170 return std::move(*this);
171}
172
174{
175 MoveFrom(this, std::move(next));
176}
177
179{
180 QueryCallbackData& callback = _callbacks.front();
181 auto checkStateAndReturnCompletion = [this]()
182 {
183 _callbacks.pop();
184 bool hasNext = !_isPrepared ? _string.valid() : _prepared.valid();
185 if (_callbacks.empty())
186 {
187 ASSERT(!hasNext);
188 return true;
189 }
190
191 // abort chain
192 if (!hasNext)
193 return true;
194
195 ASSERT(_isPrepared == _callbacks.front()._isPrepared);
196 return false;
197 };
198
199 if (!_isPrepared)
200 {
201 if (_string.valid() && _string.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
202 {
203 QueryResultFuture f(std::move(_string));
204 std::function<void(QueryCallback&, QueryResult)> cb(std::move(callback._string));
205 cb(*this, f.get());
206 return checkStateAndReturnCompletion();
207 }
208 }
209 else
210 {
211 if (_prepared.valid() && _prepared.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
212 {
214 std::function<void(QueryCallback&, PreparedQueryResult)> cb(std::move(callback._prepared));
215 cb(*this, f.get());
216 return checkStateAndReturnCompletion();
217 }
218 }
219
220 return false;
221}
std::future< PreparedQueryResult > PreparedQueryResultFuture
std::future< QueryResult > QueryResultFuture
std::shared_ptr< ResultSet > QueryResult
std::shared_ptr< PreparedResultSet > PreparedQueryResult
#define ASSERT
Definition: Errors.h:68
void Construct(T &t, Args &&... args)
void MoveFrom(T *to, T &&from)
void ConstructActiveMember(T *obj)
void Destroy(T &t)
void DestroyActiveMember(T *obj)
std::queue< QueryCallbackData, std::list< QueryCallbackData > > _callbacks
Definition: QueryCallback.h:64
QueryResultFuture _string
Definition: QueryCallback.h:58
PreparedQueryResultFuture _prepared
Definition: QueryCallback.h:59
friend void MoveFrom(T *to, T &&from)
QueryCallback && WithCallback(std::function< void(QueryResult)> &&callback)
QueryCallback(QueryResultFuture &&result)
QueryCallback & operator=(QueryCallback &&right) noexcept
void SetNextQuery(QueryCallback &&next)
QueryCallback && WithChainingPreparedCallback(std::function< void(QueryCallback &, PreparedQueryResult)> &&callback)
friend void DestroyActiveMember(T *obj)
QueryCallback && WithChainingCallback(std::function< void(QueryCallback &, QueryResult)> &&callback)
QueryCallback && WithPreparedCallback(std::function< void(PreparedQueryResult)> &&callback)
STL namespace.
QueryCallbackData & operator=(QueryCallbackData &&right) noexcept
std::function< void(QueryCallback &, QueryResult)> _string
QueryCallbackData(std::function< void(QueryCallback &, QueryResult)> &&callback)
friend void MoveFrom(T *to, T &&from)
QueryCallbackData & operator=(QueryCallbackData const &)=delete
friend void ConstructActiveMember(T *obj)
QueryCallbackData(QueryCallbackData &&right) noexcept
friend void DestroyActiveMember(T *obj)
std::function< void(QueryCallback &, PreparedQueryResult)> _prepared
QueryCallbackData(QueryCallbackData const &)=delete
QueryCallbackData(std::function< void(QueryCallback &, PreparedQueryResult)> &&callback)