diff options
-rw-r--r-- | http/http_response.hpp | 37 | ||||
-rw-r--r-- | include/async_resp.hpp | 2 | ||||
-rw-r--r-- | redfish-core/include/utils/query_param.hpp | 9 |
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; } |