summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--http/http_response.hpp37
-rw-r--r--include/async_resp.hpp2
-rw-r--r--redfish-core/include/utils/query_param.hpp9
3 files changed, 39 insertions, 9 deletions
diff --git a/http/http_response.hpp b/http/http_response.hpp
index 71d3377461..38bebb5c8a 100644
--- a/http/http_response.hpp
+++ b/http/http_response.hpp
@@ -40,10 +40,23 @@ struct Response
Response() : stringResponse(response_type{})
{}
+ Response(Response&& res) noexcept :
+ stringResponse(std::move(res.stringResponse)), completed(res.completed)
+ {
+ jsonValue = std::move(res.jsonValue);
+ // See note in operator= move handler for why this is needed.
+ if (!res.completed)
+ {
+ completeRequestHandler = std::move(res.completeRequestHandler);
+ res.completeRequestHandler = nullptr;
+ }
+ isAliveHelper = res.isAliveHelper;
+ res.isAliveHelper = nullptr;
+ }
+
~Response() = default;
Response(const Response&) = delete;
- Response(Response&&) = delete;
Response& operator=(const Response& r) = delete;
@@ -58,10 +71,23 @@ struct Response
stringResponse = std::move(r.stringResponse);
r.stringResponse.emplace(response_type{});
jsonValue = std::move(r.jsonValue);
+
+ // Only need to move completion handler if not already completed
+ // Note, there are cases where we might move out of a Response object
+ // while in a completion handler for that response object. This check
+ // is intended to prevent destructing the functor we are currently
+ // executing from in that case.
+ if (!r.completed)
+ {
+ completeRequestHandler = std::move(r.completeRequestHandler);
+ r.completeRequestHandler = nullptr;
+ }
+ else
+ {
+ completeRequestHandler = nullptr;
+ }
completed = r.completed;
- completeRequestHandler = std::move(r.completeRequestHandler);
isAliveHelper = std::move(r.isAliveHelper);
- r.completeRequestHandler = nullptr;
r.isAliveHelper = nullptr;
return *this;
}
@@ -160,6 +186,10 @@ struct Response
{
BMCWEB_LOG_DEBUG << this << " setting completion handler";
completeRequestHandler = std::move(handler);
+
+ // Now that we have a new completion handler attached, we're no longer
+ // complete
+ completed = false;
}
std::function<void(Response&)> releaseCompleteRequestHandler()
@@ -168,6 +198,7 @@ struct Response
<< static_cast<bool>(completeRequestHandler);
std::function<void(Response&)> ret = completeRequestHandler;
completeRequestHandler = nullptr;
+ completed = true;
return ret;
}
diff --git a/include/async_resp.hpp b/include/async_resp.hpp
index 219d9df796..d7f5819142 100644
--- a/include/async_resp.hpp
+++ b/include/async_resp.hpp
@@ -16,6 +16,8 @@ class AsyncResp
{
public:
AsyncResp() = default;
+ explicit AsyncResp(crow::Response&& resIn) : res(std::move(resIn))
+ {}
AsyncResp(const AsyncResp&) = delete;
AsyncResp(AsyncResp&&) = delete;
diff --git a/redfish-core/include/utils/query_param.hpp b/redfish-core/include/utils/query_param.hpp
index 57dee3ce56..48d184b51d 100644
--- a/redfish-core/include/utils/query_param.hpp
+++ b/redfish-core/include/utils/query_param.hpp
@@ -841,14 +841,11 @@ inline void
if (query.expandType != ExpandType::None)
{
BMCWEB_LOG_DEBUG << "Executing expand query";
- // TODO(ed) this is a copy of the response object. Admittedly,
- // we're inherently doing something inefficient, but we shouldn't
- // have to do a full copy
- auto asyncResp = std::make_shared<bmcweb::AsyncResp>();
+ auto asyncResp = std::make_shared<bmcweb::AsyncResp>(
+ std::move(intermediateResponse));
+
asyncResp->res.setCompleteRequestHandler(std::move(completionHandler));
- asyncResp->res.jsonValue = std::move(intermediateResponse.jsonValue);
auto multi = std::make_shared<MultiAsyncResp>(app, asyncResp);
-
multi->startQuery(query);
return;
}