diff --git a/folly/io/async/Request.cpp b/folly/io/async/Request.cpp index eb8598295b9..16a2bd3aa47 100644 --- a/folly/io/async/Request.cpp +++ b/folly/io/async/Request.cpp @@ -24,11 +24,6 @@ #include #include -DEFINE_bool( - folly_reqctx_use_hazptr, - true, - "RequestContext implementation using hazard pointers"); - namespace folly { namespace { @@ -118,33 +113,10 @@ void RequestData::releaseRefClearDeleteSlow() { releaseRefDeleteOnly(); } -void RequestData::DestructPtr::operator()(RequestData* ptr) { - if (ptr) { - auto keepAliveCounter = - ptr->keepAliveCounter_.fetch_sub(1, std::memory_order_acq_rel); - // Note: this is the value before decrement, hence == 1 check - DCHECK(keepAliveCounter > 0); - if (keepAliveCounter == 1) { - ptr->onClear(); - delete ptr; - } - } -} - -/* static */ RequestData::SharedPtr RequestData::constructPtr( - RequestData* ptr) { - if (ptr) { - auto keepAliveCounter = - ptr->keepAliveCounter_.fetch_add(1, std::memory_order_relaxed); - DCHECK(keepAliveCounter >= 0); - } - return SharedPtr(ptr); -} - // The Combined struct keeps the two structures for context data // and callbacks together, so that readers can protect consistent // versions of the two structures together using hazard pointers. -struct RequestContext::StateHazptr::Combined : hazptr_obj_base { +struct RequestContext::State::Combined : hazptr_obj_base { static constexpr size_t kInitialCapacity = 4; static constexpr size_t kSlackReciprocal = 4; // unused >= 1/4 capacity @@ -218,10 +190,10 @@ struct RequestContext::StateHazptr::Combined : hazptr_obj_base { } }; // Combined -RequestContext::StateHazptr::StateHazptr() = default; +RequestContext::State::State() = default; FOLLY_ALWAYS_INLINE -RequestContext::StateHazptr::StateHazptr(const StateHazptr& o) { +RequestContext::State::State(const State& o) { Combined* oc = o.combined(); if (oc) { auto p = new Combined(*oc); @@ -230,7 +202,7 @@ RequestContext::StateHazptr::StateHazptr(const StateHazptr& o) { } } -RequestContext::StateHazptr::~StateHazptr() { +RequestContext::State::~State() { cohort_.shutdown_and_reclaim(); auto p = combined(); if (p) { @@ -239,14 +211,12 @@ RequestContext::StateHazptr::~StateHazptr() { } FOLLY_ALWAYS_INLINE -RequestContext::StateHazptr::Combined* RequestContext::StateHazptr::combined() - const { +RequestContext::State::Combined* RequestContext::State::combined() const { return combined_.load(std::memory_order_acquire); } FOLLY_ALWAYS_INLINE -RequestContext::StateHazptr::Combined* -RequestContext::StateHazptr::ensureCombined() { +RequestContext::State::Combined* RequestContext::State::ensureCombined() { auto c = combined(); if (!c) { c = new Combined; @@ -256,13 +226,13 @@ RequestContext::StateHazptr::ensureCombined() { } FOLLY_ALWAYS_INLINE -void RequestContext::StateHazptr::setCombined(Combined* p) { +void RequestContext::State::setCombined(Combined* p) { p->set_cohort_tag(&cohort_); combined_.store(p, std::memory_order_release); } FOLLY_ALWAYS_INLINE -bool RequestContext::StateHazptr::doSetContextData( +bool RequestContext::State::doSetContextData( const RequestToken& token, std::unique_ptr& data, DoSetBehaviour behaviour, @@ -286,8 +256,8 @@ bool RequestContext::StateHazptr::doSetContextData( } FOLLY_ALWAYS_INLINE -RequestContext::StateHazptr::SetContextDataResult -RequestContext::StateHazptr::doSetContextDataHelper( +RequestContext::State::SetContextDataResult +RequestContext::State::doSetContextDataHelper( const RequestToken& token, std::unique_ptr& data, DoSetBehaviour behaviour, @@ -341,9 +311,9 @@ RequestContext::StateHazptr::doSetContextDataHelper( } FOLLY_ALWAYS_INLINE -RequestContext::StateHazptr::Combined* FOLLY_NULLABLE -RequestContext::StateHazptr::eraseOldData( - RequestContext::StateHazptr::Combined* cur, +RequestContext::State::Combined* FOLLY_NULLABLE +RequestContext::State::eraseOldData( + RequestContext::State::Combined* cur, const RequestToken& token, RequestData* olddata, bool safe) { @@ -375,9 +345,9 @@ RequestContext::StateHazptr::eraseOldData( } FOLLY_ALWAYS_INLINE -RequestContext::StateHazptr::Combined* FOLLY_NULLABLE -RequestContext::StateHazptr::insertNewData( - RequestContext::StateHazptr::Combined* cur, +RequestContext::State::Combined* FOLLY_NULLABLE +RequestContext::State::insertNewData( + RequestContext::State::Combined* cur, const RequestToken& token, std::unique_ptr& data, bool found) { @@ -404,8 +374,7 @@ RequestContext::StateHazptr::insertNewData( } FOLLY_ALWAYS_INLINE -bool RequestContext::StateHazptr::hasContextData( - const RequestToken& token) const { +bool RequestContext::State::hasContextData(const RequestToken& token) const { hazptr_local<1> h; Combined* combined = h[0].get_protected(combined_); return combined ? combined->requestData_.contains(token) : false; @@ -413,7 +382,7 @@ bool RequestContext::StateHazptr::hasContextData( FOLLY_ALWAYS_INLINE RequestData* FOLLY_NULLABLE -RequestContext::StateHazptr::getContextData(const RequestToken& token) { +RequestContext::State::getContextData(const RequestToken& token) { hazptr_local<1> h; Combined* combined = h[0].get_protected(combined_); if (!combined) { @@ -426,7 +395,7 @@ RequestContext::StateHazptr::getContextData(const RequestToken& token) { FOLLY_ALWAYS_INLINE const RequestData* FOLLY_NULLABLE -RequestContext::StateHazptr::getContextData(const RequestToken& token) const { +RequestContext::State::getContextData(const RequestToken& token) const { hazptr_local<1> h; Combined* combined = h[0].get_protected(combined_); if (!combined) { @@ -438,7 +407,7 @@ RequestContext::StateHazptr::getContextData(const RequestToken& token) const { } FOLLY_ALWAYS_INLINE -void RequestContext::StateHazptr::onSet() { +void RequestContext::State::onSet() { // Don't use hazptr_local because callback may use hazptr hazptr_holder<> h; Combined* combined = h.get_protected(combined_); @@ -452,7 +421,7 @@ void RequestContext::StateHazptr::onSet() { } FOLLY_ALWAYS_INLINE -void RequestContext::StateHazptr::onUnset() { +void RequestContext::State::onUnset() { // Don't use hazptr_local because callback may use hazptr hazptr_holder<> h; Combined* combined = h.get_protected(combined_); @@ -465,7 +434,7 @@ void RequestContext::StateHazptr::onUnset() { } } -void RequestContext::StateHazptr::clearContextData(const RequestToken& token) { +void RequestContext::State::clearContextData(const RequestToken& token) { RequestData* data; Combined* replaced = nullptr; { // Lock mutex_ @@ -503,8 +472,8 @@ void RequestContext::StateHazptr::clearContextData(const RequestToken& token) { replaced->retire(); } -RequestContext::StateHazptr::Combined* RequestContext::StateHazptr::expand( - RequestContext::StateHazptr::Combined* c) { +RequestContext::State::Combined* RequestContext::State::expand( + RequestContext::State::Combined* c) { size_t dataCapacity = c->requestData_.capacity(); if (c->needExpandRequestData()) { dataCapacity *= 2; @@ -516,12 +485,9 @@ RequestContext::StateHazptr::Combined* RequestContext::StateHazptr::expand( return new Combined(dataCapacity, callbackCapacity, *c); } -RequestContext::RequestContext() - : useHazptr_(FLAGS_folly_reqctx_use_hazptr), - rootId_(reinterpret_cast(this)) {} +RequestContext::RequestContext() : rootId_(reinterpret_cast(this)) {} -RequestContext::RequestContext(intptr_t rootid) - : useHazptr_(FLAGS_folly_reqctx_use_hazptr), rootId_(rootid) {} +RequestContext::RequestContext(intptr_t rootid) : rootId_(rootid) {} RequestContext::RequestContext(const RequestContext& ctx, intptr_t rootid, Tag) : RequestContext(ctx) { @@ -542,183 +508,51 @@ RequestContext::RequestContext(const RequestContext& ctx, Tag) return std::make_shared(ctx, Tag{}); } -bool RequestContext::doSetContextDataLock( - const RequestToken& token, - std::unique_ptr& data, - DoSetBehaviour behaviour) { - auto wlock = state_.wlock(); - auto& state = *wlock; - - auto it = state.requestData_.find(token); - if (it != state.requestData_.end()) { - if (behaviour == DoSetBehaviour::SET_IF_ABSENT) { - return false; - } - if (it->second) { - if (it->second->hasCallback()) { - it->second->onUnset(); - state.callbackData_.erase(it->second.get()); - } - it->second.reset(nullptr); - } - if (behaviour == DoSetBehaviour::SET) { - LOG_FIRST_N(WARNING, 1) - << "Calling RequestContext::setContextData for " - << token.getDebugString() << " but it is already set"; - return true; - } - DCHECK(behaviour == DoSetBehaviour::OVERWRITE); - } - - if (data && data->hasCallback()) { - state.callbackData_.insert(data.get()); - data->onSet(); - } - auto ptr = RequestData::constructPtr(data.release()); - if (it != state.requestData_.end()) { - it->second = std::move(ptr); - } else { - state.requestData_.insert(std::make_pair(token, std::move(ptr))); - } - return true; -} - void RequestContext::setContextData( const RequestToken& token, std::unique_ptr data) { - if (useHazptr()) { - stateHazptr_.doSetContextData(token, data, DoSetBehaviour::SET, false); - return; - } - doSetContextDataLock(token, data, DoSetBehaviour::SET); + state_.doSetContextData(token, data, DoSetBehaviour::SET, false); } bool RequestContext::setContextDataIfAbsent( const RequestToken& token, std::unique_ptr data) { - if (useHazptr()) { - return stateHazptr_.doSetContextData( - token, data, DoSetBehaviour::SET_IF_ABSENT, false); - } - return doSetContextDataLock(token, data, DoSetBehaviour::SET_IF_ABSENT); -} - -void RequestContext::overwriteContextDataLock( - const RequestToken& token, - std::unique_ptr data) { - doSetContextDataLock(token, data, DoSetBehaviour::OVERWRITE); + return state_.doSetContextData( + token, data, DoSetBehaviour::SET_IF_ABSENT, false); } -void RequestContext::overwriteContextDataHazptr( +void RequestContext::overwriteContextData( const RequestToken& token, std::unique_ptr data, bool safe) { - stateHazptr_.doSetContextData(token, data, DoSetBehaviour::OVERWRITE, safe); + state_.doSetContextData(token, data, DoSetBehaviour::OVERWRITE, safe); } bool RequestContext::hasContextData(const RequestToken& val) const { - if (useHazptr()) { - return stateHazptr_.hasContextData(val); - } - return state_.rlock()->requestData_.count(val); + return state_.hasContextData(val); } RequestData* FOLLY_NULLABLE RequestContext::getContextData(const RequestToken& val) { - if (useHazptr()) { - return stateHazptr_.getContextData(val); - } - const RequestData::SharedPtr dflt{nullptr}; - return get_ref_default(state_.rlock()->requestData_, val, dflt).get(); + return state_.getContextData(val); } const RequestData* FOLLY_NULLABLE RequestContext::getContextData(const RequestToken& val) const { - if (useHazptr()) { - return stateHazptr_.getContextData(val); - } - const RequestData::SharedPtr dflt{nullptr}; - return get_ref_default(state_.rlock()->requestData_, val, dflt).get(); + return state_.getContextData(val); } void RequestContext::onSet() { - if (useHazptr()) { - stateHazptr_.onSet(); - return; - } - auto rlock = state_.rlock(); - for (const auto& data : rlock->callbackData_) { - data->onSet(); - } + state_.onSet(); } void RequestContext::onUnset() { - if (useHazptr()) { - stateHazptr_.onUnset(); - return; - } - auto rlock = state_.rlock(); - for (const auto& data : rlock->callbackData_) { - data->onUnset(); - } + state_.onUnset(); } void RequestContext::clearContextData(const RequestToken& val) { - if (useHazptr()) { - stateHazptr_.clearContextData(val); - return; - } - RequestData::SharedPtr requestData; - // Delete the RequestData after giving up the wlock just in case one of the - // RequestData destructors will try to grab the lock again. - { - auto ulock = state_.ulock(); - // Need non-const iterators to use under write lock. - auto& state = ulock.asNonConstUnsafe(); - auto it = state.requestData_.find(val); - if (it == state.requestData_.end()) { - return; - } - - auto wlock = ulock.moveFromUpgradeToWrite(); - if (it->second && it->second->hasCallback()) { - it->second->onUnset(); - wlock->callbackData_.erase(it->second.get()); - } - - requestData = std::move(it->second); - wlock->requestData_.erase(it); - } -} - -namespace { -// Execute functor exec for all RequestData in data, which are not in other -// Similar to std::set_difference but avoid intermediate data structure -template -void exec_set_difference(const TData& data, const TData& other, TExec&& exec) { - auto diter = data.begin(); - auto dend = data.end(); - auto oiter = other.begin(); - auto oend = other.end(); - while (diter != dend) { - // Order of "if" optimizes for the 2 common cases: - // 1) empty other, switching to default context - // 2) identical other, switching to similar context with same callbacks - if (oiter == oend) { - exec(*diter); - ++diter; - } else if (*diter == *oiter) { - ++diter; - ++oiter; - } else if (*diter < *oiter) { - exec(*diter); - ++diter; - } else { - ++oiter; - } - } + state_.clearContextData(val); } -} // namespace /* static */ std::shared_ptr RequestContext::setContext( std::shared_ptr const& newCtx) { @@ -742,62 +576,14 @@ void exec_set_difference(const TData& data, const TData& other, TExec&& exec) { staticCtx.first ? staticCtx.first->getRootId() : 0, newCtx ? newCtx->getRootId() : 0); - if ((newCtx.get() && newCtx->useHazptr()) || - (staticCtx.first.get() && staticCtx.first->useHazptr())) { - DCHECK(!newCtx.get() || newCtx->useHazptr()); - DCHECK(!staticCtx.first.get() || staticCtx.first->useHazptr()); - return RequestContext::setContextHazptr(newCtx, staticCtx); - } else { - return RequestContext::setContextLock(newCtx, staticCtx); - } -} - -FOLLY_ALWAYS_INLINE -/* static */ std::shared_ptr RequestContext::setContextLock( - std::shared_ptr& newCtx, - StaticContext& staticCtx) { - auto curCtx = staticCtx.first; - if (newCtx && curCtx) { - // Only call set/unset for all request data that differs - auto ret = folly::acquireLocked( - as_const(newCtx->state_), as_const(curCtx->state_)); - auto& newLock = std::get<0>(ret); - auto& curLock = std::get<1>(ret); - auto& newData = newLock->callbackData_; - auto& curData = curLock->callbackData_; - exec_set_difference( - curData, newData, [](RequestData* data) { data->onUnset(); }); - staticCtx.first = newCtx; - staticCtx.second.store(newCtx->rootId_, std::memory_order_relaxed); - exec_set_difference( - newData, curData, [](RequestData* data) { data->onSet(); }); - } else { - if (curCtx) { - curCtx->onUnset(); - } - staticCtx.first = newCtx; - if (newCtx) { - staticCtx.second.store(newCtx->rootId_, std::memory_order_relaxed); - newCtx->onSet(); - } else { - staticCtx.second.store(0, std::memory_order_relaxed); - } - } - return curCtx; -} - -FOLLY_ALWAYS_INLINE -/* static */ std::shared_ptr RequestContext::setContextHazptr( - std::shared_ptr& newCtx, - StaticContext& staticCtx) { std::shared_ptr prevCtx; - auto curCtx = staticCtx.first.get(); - bool checkCur = curCtx && curCtx->stateHazptr_.combined(); - bool checkNew = newCtx && newCtx->stateHazptr_.combined(); + RequestContext* curCtx = staticCtx.first.get(); + bool checkCur = curCtx && curCtx->state_.combined(); + bool checkNew = newCtx && newCtx->state_.combined(); if (checkCur && checkNew) { hazptr_array<2> h; - auto curc = h[0].get_protected(curCtx->stateHazptr_.combined_); - auto newc = h[1].get_protected(newCtx->stateHazptr_.combined_); + auto curc = h[0].get_protected(curCtx->state_.combined_); + auto newc = h[1].get_protected(newCtx->state_.combined_); auto& curcb = curc->callbackData_; auto& newcb = newc->callbackData_; for (auto it = curcb.begin(); it != curcb.end(); ++it) { @@ -819,14 +605,14 @@ FOLLY_ALWAYS_INLINE } } else { if (curCtx) { - curCtx->stateHazptr_.onUnset(); + curCtx->state_.onUnset(); } prevCtx = std::move(staticCtx.first); staticCtx.first = std::move(newCtx); if (staticCtx.first) { staticCtx.second.store( staticCtx.first->rootId_, std::memory_order_relaxed); - staticCtx.first->stateHazptr_.onSet(); + staticCtx.first->state_.onSet(); } else { staticCtx.second.store(0, std::memory_order_relaxed); } diff --git a/folly/io/async/Request.h b/folly/io/async/Request.h index fd465fcd507..3dd7bb60866 100644 --- a/folly/io/async/Request.h +++ b/folly/io/async/Request.h @@ -18,7 +18,6 @@ #include #include -#include #include #include @@ -27,8 +26,6 @@ #include #include -DECLARE_bool(folly_reqctx_use_hazptr); - namespace folly { /* @@ -72,18 +69,6 @@ struct hash { namespace folly { -// - A runtime flag GFLAGS_reqctx_use_hazptr determines the -// implementation of RequestContext. -// - The flag false implementation uses sequential data structures -// protected by a read-write lock. -// - The flag true implementation uses single-writer multi-readers -// data structures protected by hazard pointers for readers and a -// lock for writers. -// - Each RequestContext instances contains a bool member useHazptr_ -// (readable by a public member function useHazptr()) that indicates -// the implementation of the instance depending on the value of the -// GFLAG at instance construction time.. - // Some request context that follows an async request through a process // Everything in the context must be thread safe @@ -120,7 +105,6 @@ class RequestData { } private: - // Start shallow copy implementation details: // For efficiency, RequestContext provides a raw ptr interface. // To support shallow copy, we need a shared ptr. // To keep it as safe as possible (even if a raw ptr is passed back), @@ -131,8 +115,8 @@ class RequestData { static constexpr int kDeleteCount = 0x1; static constexpr int kClearCount = 0x1000; - // Reference-counting functions used by the hazptr-based implementation. - // Increment the reference count + // Reference-counting functions. + // Increment the reference count. void acquireRef(); // Decrement the reference count. Clear only if last. void releaseRefClearOnly(); @@ -142,27 +126,7 @@ class RequestData { void releaseRefClearDelete(); void releaseRefClearDeleteSlow(); - // Unique ptr with custom destructor, decrement the counter - // and only free if 0 - struct DestructPtr { - void operator()(RequestData* ptr); - }; - struct SharedPtr : public std::unique_ptr { - SharedPtr() = default; - using std::unique_ptr::unique_ptr; - SharedPtr(const SharedPtr& other) : SharedPtr(constructPtr(other.get())) {} - SharedPtr& operator=(const SharedPtr& other) { - return operator=(constructPtr(other.get())); - } - SharedPtr(SharedPtr&&) = default; - SharedPtr& operator=(SharedPtr&&) = default; - }; - - // Initialize the pseudo-shared ptr, increment the counter - static SharedPtr constructPtr(RequestData* ptr); - std::atomic keepAliveCounter_{0}; - // End shallow copy }; // If you do not call create() to create a unique request context, @@ -260,11 +224,6 @@ class RequestContext { void onSet(); void onUnset(); - // useHazptr - FOLLY_ALWAYS_INLINE bool useHazptr() const { - return useHazptr_; - } - // The following API is used to pass the context through queues / threads. // saveContext is called to get a shared_ptr to the context, and // setContext is used to reset it on the other side of the queue. @@ -297,11 +256,7 @@ class RequestContext { private: static StaticContext& getStaticContext(); - - static std::shared_ptr setContextLock( - std::shared_ptr& newCtx, - StaticContext& staticCtx); - static std::shared_ptr setContextHazptr( + static std::shared_ptr setContextHelper( std::shared_ptr& newCtx, StaticContext& staticCtx); @@ -313,30 +268,18 @@ class RequestContext { // then return the previous context (so it can be reset later). static std::shared_ptr setShallowCopyContext(); - // Similar to setContextData, except it overwrites the data - // if already set (instead of warn + reset ptr). - void overwriteContextDataLock( - const RequestToken& token, - std::unique_ptr data); - void overwriteContextDataLock( - const std::string& val, - std::unique_ptr data) { - overwriteContextDataLock(RequestToken(val), std::move(data)); - } - // End shallow copy guard - // For functions with a parameter safe, if safe is true then the // caller guarantees that there are no concurrent readers or writers // accessing the structure. - void overwriteContextDataHazptr( + void overwriteContextData( const RequestToken& token, std::unique_ptr data, bool safe = false); - void overwriteContextDataHazptr( + void overwriteContextData( const std::string& val, std::unique_ptr data, bool safe = false) { - overwriteContextDataHazptr(RequestToken(val), std::move(data), safe); + overwriteContextData(RequestToken(val), std::move(data), safe); } enum class DoSetBehaviour { @@ -345,47 +288,23 @@ class RequestContext { OVERWRITE, }; - bool doSetContextDataLock( - const RequestToken& token, - std::unique_ptr& data, - DoSetBehaviour behaviour); - bool doSetContextDataLock( - const std::string& val, - std::unique_ptr& data, - DoSetBehaviour behaviour) { - return doSetContextDataLock(RequestToken(val), data, behaviour); - } - - bool doSetContextDataHazptr( + bool doSetContextDataHelper( const RequestToken& token, std::unique_ptr& data, DoSetBehaviour behaviour, bool safe = false); - bool doSetContextDataHazptr( + bool doSetContextDataHelper( const std::string& val, std::unique_ptr& data, DoSetBehaviour behaviour, bool safe = false) { - return doSetContextDataHazptr(RequestToken(val), data, behaviour, safe); + return doSetContextDataHelper(RequestToken(val), data, behaviour, safe); } - // State immplementation with sequential data structures protected by a - // read-write locks. - struct State { - // This must be optimized for lookup, its hot path is getContextData - // Efficiency of copying the container also matters in setShallowCopyContext - F14FastMap requestData_; - // This must be optimized for iteration, its hot path is setContext - // We also use the fact that it's ordered to efficiently compute - // the difference with previous context - sorted_vector_set callbackData_; - }; - folly::Synchronized state_; - // State implementation with single-writer multi-reader data // structures protected by hazard pointers for readers and a lock // for writers. - struct StateHazptr { + struct State { // Hazard pointer-protected combined structure for request data // and callbacks. struct Combined; @@ -393,12 +312,12 @@ class RequestContext { std::atomic combined_{nullptr}; std::mutex mutex_; - StateHazptr(); - StateHazptr(const StateHazptr& o); - StateHazptr(StateHazptr&&) = delete; - StateHazptr& operator=(const StateHazptr&) = delete; - StateHazptr& operator=(StateHazptr&&) = delete; - ~StateHazptr(); + State(); + State(const State& o); + State(State&&) = delete; + State& operator=(const State&) = delete; + State& operator=(State&&) = delete; + ~State(); private: friend class RequestContext; @@ -439,9 +358,8 @@ class RequestContext { const RequestToken& token, std::unique_ptr& data, bool found); - }; // StateHazptr - StateHazptr stateHazptr_; - bool useHazptr_; + }; // State + State state_; // Shallow copies keep a note of the root context intptr_t rootId_; }; @@ -499,23 +417,13 @@ struct ShallowCopyRequestContextScopeGuard { const RequestToken& token, std::unique_ptr data) : ShallowCopyRequestContextScopeGuard() { - auto ctx = RequestContext::get(); - if (ctx->useHazptr()) { - ctx->overwriteContextDataHazptr(token, std::move(data), true); - } else { - ctx->overwriteContextDataLock(token, std::move(data)); - } + RequestContext::get()->overwriteContextData(token, std::move(data), true); } ShallowCopyRequestContextScopeGuard( const std::string& val, std::unique_ptr data) : ShallowCopyRequestContextScopeGuard() { - auto ctx = RequestContext::get(); - if (ctx->useHazptr()) { - ctx->overwriteContextDataHazptr(val, std::move(data), true); - } else { - ctx->overwriteContextDataLock(val, std::move(data)); - } + RequestContext::get()->overwriteContextData(val, std::move(data), true); } ~ShallowCopyRequestContextScopeGuard() { diff --git a/folly/io/async/test/RequestContextBenchmark.cpp b/folly/io/async/test/RequestContextBenchmark.cpp index 98ddbbefc81..7fe7a4393a3 100644 --- a/folly/io/async/test/RequestContextBenchmark.cpp +++ b/folly/io/async/test/RequestContextBenchmark.cpp @@ -300,8 +300,8 @@ onSet 12 ns 12 ns 0 ns 12 ns onUnset 12 ns 12 ns 0 ns 12 ns setContext 46 ns 44 ns 1 ns 42 ns RequestContextScopeGuard 113 ns 103 ns 3 ns 101 ns -ShallowCopyRequestC...-replace 230 ns 221 ns 4 ns 217 ns -ShallowCopyReq...-keep&replace 904 ns 893 ns 5 ns 886 ns +ShallowCopyRequestC...-replace 213 ns 201 ns 5 ns 196 ns +ShallowCopyReq...-keep&replace 883 ns 835 ns 20 ns 814 ns ============================== 10 threads ============================== hasContextData 1 ns 1 ns 0 ns 1 ns getContextData 2 ns 1 ns 0 ns 1 ns @@ -309,7 +309,7 @@ onSet 2 ns 2 ns 0 ns 1 ns onUnset 2 ns 2 ns 0 ns 1 ns setContext 11 ns 7 ns 2 ns 5 ns RequestContextScopeGuard 22 ns 15 ns 5 ns 11 ns -ShallowCopyRequestC...-replace 51 ns 32 ns 11 ns 24 ns -ShallowCopyReq...-keep&replace 102 ns 98 ns 2 ns 96 ns +ShallowCopyRequestC...-replace 48 ns 30 ns 11 ns 21 ns +ShallowCopyReq...-keep&replace 98 ns 93 ns 2 ns 91 ns ======================================================================== */