Commit e03e7630 authored by Joe Loser's avatar Joe Loser Committed by Facebook Github Bot

Cut backport of std::exchange (#1021)

Summary:
- Backporting `std:exchange` is no longer needed as Folly requires C++14
  support and C++14-compliant vendors have `std::exchange` in their
  standard library, notably including GCC 4.9.
- Cut backport of `std::exchange` and fix call sites to explicitly use
  `std::exchange` where they were previously relying on `exchange` being
  found in the `folly` namespace.
Pull Request resolved: https://github.com/facebook/folly/pull/1021

Reviewed By: Orvid

Differential Revision: D14119875

Pulled By: yfeldblum

fbshipit-source-id: 686a8e812f6728281b432eae1586de28d21da9dd
parent 6e296e64
......@@ -18,6 +18,7 @@
#include <cassert>
#include <climits>
#include <utility>
#include <folly/Function.h>
#include <folly/Utility.h>
......@@ -59,7 +60,8 @@ class Executor {
}
KeepAlive(KeepAlive&& other) noexcept
: executorAndDummyFlag_(exchange(other.executorAndDummyFlag_, 0)) {}
: executorAndDummyFlag_(std::exchange(other.executorAndDummyFlag_, 0)) {
}
KeepAlive(const KeepAlive& other) noexcept
: KeepAlive(getKeepAliveToken(other.get())) {}
......@@ -86,7 +88,7 @@ class Executor {
KeepAlive& operator=(KeepAlive&& other) {
reset();
executorAndDummyFlag_ = exchange(other.executorAndDummyFlag_, 0);
executorAndDummyFlag_ = std::exchange(other.executorAndDummyFlag_, 0);
return *this;
}
......@@ -108,7 +110,7 @@ class Executor {
void reset() {
if (Executor* executor = get()) {
if (exchange(executorAndDummyFlag_, 0) & kDummyFlag) {
if (std::exchange(executorAndDummyFlag_, 0) & kDummyFlag) {
return;
}
executor->keepAliveRelease();
......
......@@ -90,7 +90,7 @@ class ScopeGuardImpl : public ScopeGuardImplBase {
// on the value of other.dismissed_. The following lines only execute
// if the move/copy succeeded, in which case *this assumes ownership of
// the cleanup action and dismisses other.
dismissed_ = exchange(other.dismissed_, true);
dismissed_ = std::exchange(other.dismissed_, true);
}
~ScopeGuardImpl() noexcept(InvokeNoexcept) {
......
......@@ -1086,7 +1086,7 @@ class LockedPtrBase {
}
}
LockedPtrBase(LockedPtrBase&& rhs) noexcept
: parent_{exchange(rhs.parent_, nullptr)} {}
: parent_{std::exchange(rhs.parent_, nullptr)} {}
LockedPtrBase& operator=(LockedPtrBase&& rhs) noexcept {
assignImpl(*this, rhs);
return *this;
......@@ -1107,7 +1107,7 @@ class LockedPtrBase {
template <typename LockPolicyType>
LockedPtrBase(
LockedPtrBase<SynchronizedType, Mutex, LockPolicyType>&& rhs) noexcept
: parent_{exchange(rhs.parent_, nullptr)} {}
: parent_{std::exchange(rhs.parent_, nullptr)} {}
template <typename LockPolicyType>
LockedPtrBase& operator=(
LockedPtrBase<SynchronizedType, Mutex, LockPolicyType>&& rhs) noexcept {
......@@ -1126,7 +1126,7 @@ class LockedPtrBase {
LockPolicy::unlock(lhs.parent_->mutex_);
}
lhs.parent_ = exchange(rhs.parent_, nullptr);
lhs.parent_ = std::exchange(rhs.parent_, nullptr);
}
using UnlockerData = SynchronizedType*;
......@@ -1188,7 +1188,8 @@ class LockedPtrBase<SynchronizedType, std::mutex, LockPolicy> {
}
LockedPtrBase(LockedPtrBase&& rhs) noexcept
: lock_{std::move(rhs.lock_)}, parent_{exchange(rhs.parent_, nullptr)} {}
: lock_{std::move(rhs.lock_)},
parent_{std::exchange(rhs.parent_, nullptr)} {}
LockedPtrBase& operator=(LockedPtrBase&& rhs) noexcept {
assignImpl(*this, rhs);
return *this;
......@@ -1204,7 +1205,7 @@ class LockedPtrBase<SynchronizedType, std::mutex, LockPolicy> {
LockedPtrBase(LockedPtrBase<SynchronizedType, std::mutex, LockPolicyType>&&
other) noexcept
: lock_{std::move(other.lock_)},
parent_{exchange(other.parent_, nullptr)} {}
parent_{std::exchange(other.parent_, nullptr)} {}
template <typename LockPolicyType>
LockedPtrBase& operator=(
LockedPtrBase<SynchronizedType, std::mutex, LockPolicyType>&&
......@@ -1222,7 +1223,7 @@ class LockedPtrBase<SynchronizedType, std::mutex, LockPolicy> {
LockedPtrBase<SynchronizedType, std::mutex, LockPolicyRhs>&
rhs) noexcept {
lhs.lock_ = std::move(rhs.lock_);
lhs.parent_ = exchange(rhs.parent_, nullptr);
lhs.parent_ = std::exchange(rhs.parent_, nullptr);
}
/**
......@@ -1301,7 +1302,8 @@ class ScopedUnlocker {
ScopedUnlocker(const ScopedUnlocker&) = delete;
ScopedUnlocker& operator=(const ScopedUnlocker&) = delete;
ScopedUnlocker(ScopedUnlocker&& other) noexcept
: ptr_(exchange(other.ptr_, nullptr)), data_(std::move(other.data_)) {}
: ptr_(std::exchange(other.ptr_, nullptr)),
data_(std::move(other.data_)) {}
ScopedUnlocker& operator=(ScopedUnlocker&& other) = delete;
~ScopedUnlocker() {
......@@ -1521,7 +1523,7 @@ class LockedPtr : public LockedPtrBase<
LockedPtr<SynchronizedType, LockPolicyFromUpgradeToExclusive>
moveFromUpgradeToWrite() {
return LockedPtr<SynchronizedType, LockPolicyFromUpgradeToExclusive>(
exchange(this->parent_, nullptr));
std::exchange(this->parent_, nullptr));
}
/**
......@@ -1535,7 +1537,7 @@ class LockedPtr : public LockedPtrBase<
LockedPtr<SynchronizedType, LockPolicyFromExclusiveToUpgrade>
moveFromWriteToUpgrade() {
return LockedPtr<SynchronizedType, LockPolicyFromExclusiveToUpgrade>(
exchange(this->parent_, nullptr));
std::exchange(this->parent_, nullptr));
}
/**
......@@ -1549,7 +1551,7 @@ class LockedPtr : public LockedPtrBase<
LockedPtr<SynchronizedType, LockPolicyFromUpgradeToShared>
moveFromUpgradeToRead() {
return LockedPtr<SynchronizedType, LockPolicyFromUpgradeToShared>(
exchange(this->parent_, nullptr));
std::exchange(this->parent_, nullptr));
}
/**
......@@ -1563,7 +1565,7 @@ class LockedPtr : public LockedPtrBase<
LockedPtr<SynchronizedType, LockPolicyFromExclusiveToShared>
moveFromWriteToRead() {
return LockedPtr<SynchronizedType, LockPolicyFromExclusiveToShared>(
exchange(this->parent_, nullptr));
std::exchange(this->parent_, nullptr));
}
};
......
......@@ -21,6 +21,7 @@
#include <stdexcept>
#include <tuple>
#include <utility>
namespace folly {
......@@ -174,7 +175,7 @@ void Try<T>::throwIfFailed() const {
template <class T>
void Try<T>::destroy() noexcept {
auto oldContains = folly::exchange(contains_, Contains::NOTHING);
auto oldContains = std::exchange(contains_, Contains::NOTHING);
if (LIKELY(oldContains == Contains::VALUE)) {
value_.~T();
} else if (UNLIKELY(oldContains == Contains::EXCEPTION)) {
......
......@@ -108,23 +108,6 @@ constexpr like_t<Src, Dst>&& forward_like(Dst&& dst) noexcept {
return static_cast<like_t<Src, Dst>&&>(std::forward<Dst>(dst));
}
#if __cpp_lib_exchange_function || _LIBCPP_STD_VER > 11 || _MSC_VER
/* using override */ using std::exchange;
#else
// mimic: std::exchange, C++14
// from: http://en.cppreference.com/w/cpp/utility/exchange, CC-BY-SA
template <class T, class U = T>
T exchange(T& obj, U&& new_value) {
T old_value = std::move(obj);
obj = std::forward<U>(new_value);
return old_value;
}
#endif
namespace utility_detail {
template <typename...>
struct make_seq_cat;
......
......@@ -19,6 +19,7 @@
#include <cassert>
#include <chrono>
#include <thread>
#include <utility>
#include <folly/Optional.h>
#include <folly/executors/ExecutorWithPriority.h>
......@@ -167,7 +168,7 @@ FutureBase<T>::FutureBase(in_place_t, Args&&... args)
template <class T>
void FutureBase<T>::assign(FutureBase<T>&& other) noexcept {
detach();
core_ = exchange(other.core_, nullptr);
core_ = std::exchange(other.core_, nullptr);
}
template <class T>
......@@ -1963,7 +1964,7 @@ Future<T> unorderedReduce(It first, It last, T initial, F func) {
auto f = p.getFuture();
{
folly::MSLGuard lock(ctx->lock_);
f = exchange(ctx->memo_, std::move(f));
f = std::exchange(ctx->memo_, std::move(f));
if (++ctx->numThens_ == ctx->numFutures_) {
// After reducing the value of the last Future, fulfill the Promise
ctx->memo_.setCallback_(
......
......@@ -18,6 +18,7 @@
#include <atomic>
#include <thread>
#include <utility>
#include <folly/executors/InlineExecutor.h>
#include <folly/futures/detail/Core.h>
......@@ -47,14 +48,14 @@ Promise<T>::Promise() : retrieved_(false), core_(Core::make()) {}
template <class T>
Promise<T>::Promise(Promise<T>&& other) noexcept
: retrieved_(exchange(other.retrieved_, false)),
core_(exchange(other.core_, nullptr)) {}
: retrieved_(std::exchange(other.retrieved_, false)),
core_(std::exchange(other.core_, nullptr)) {}
template <class T>
Promise<T>& Promise<T>::operator=(Promise<T>&& other) noexcept {
detach();
retrieved_ = exchange(other.retrieved_, false);
core_ = exchange(other.core_, nullptr);
retrieved_ = std::exchange(other.retrieved_, false);
core_ = std::exchange(other.core_, nullptr);
return *this;
}
......
......@@ -538,7 +538,7 @@ class Core final {
CoreAndCallbackReference& operator=(CoreAndCallbackReference&&) = delete;
CoreAndCallbackReference(CoreAndCallbackReference&& o) noexcept
: core_(exchange(o.core_, nullptr)) {}
: core_(std::exchange(o.core_, nullptr)) {}
Core* getCore() const noexcept {
return core_;
......@@ -560,7 +560,7 @@ class Core final {
DCHECK(state_ == State::Done);
if (executor_) {
auto x = exchange(executor_, Executor::KeepAlive<>());
auto x = std::exchange(executor_, Executor::KeepAlive<>());
exception_wrapper ew;
// We need to reset `callback_` after it was executed (which can happen
......
......@@ -37,6 +37,7 @@
#include <limits>
#include <stdexcept>
#include <thread>
#include <utility>
namespace folly {
namespace detail {
......@@ -238,11 +239,11 @@ class DistributedMutex<Atomic, TimePublishing>::DistributedMutexStateProxy {
DistributedMutexStateProxy& operator=(DistributedMutexStateProxy&& other) {
DCHECK(!(*this)) << "Cannot move into a valid DistributedMutexStateProxy";
next_ = exchange(other.next_, nullptr);
expected_ = exchange(other.expected_, 0);
wakerMetadata_ = exchange(other.wakerMetadata_, {});
waiters_ = exchange(other.waiters_, nullptr);
ready_ = exchange(other.ready_, nullptr);
next_ = std::exchange(other.next_, nullptr);
expected_ = std::exchange(other.expected_, 0);
wakerMetadata_ = std::exchange(other.wakerMetadata_, {});
waiters_ = std::exchange(other.waiters_, nullptr);
ready_ = std::exchange(other.ready_, nullptr);
return *this;
}
......@@ -415,7 +416,7 @@ bool doFutexWait(Waiter* waiter, Waiter*& next) {
while (pre != kWake) {
// before enqueueing on the futex, we wake any waiters that we were
// possibly responsible for
doFutexWake(exchange(next, nullptr));
doFutexWake(std::exchange(next, nullptr));
// then we wait on the futex
//
......@@ -765,7 +766,11 @@ void DistributedMutex<Atomic, Publish>::unlock(
recordTimedWaiterAndClearTimedBit(proxy.timedWaiters_, head);
auto next = extractAddress<CachelinePadded<Waiter<Atomic>>>(head);
DCHECK((head & kLocked) && (head != kLocked)) << "incorrect state " << head;
if (wake(Publish, *next, {exchange(proxy.expected_, kLocked)}, sleepers)) {
if (wake(
Publish,
*next,
{std::exchange(proxy.expected_, kLocked)},
sleepers)) {
break;
}
}
......
......@@ -22,6 +22,7 @@
#include <memory>
#include <mutex>
#include <stdexcept>
#include <utility>
namespace folly {
namespace detail {
......@@ -75,7 +76,7 @@ template <typename Mutex>
ProxyLockableUniqueLock<Mutex>& ProxyLockableUniqueLock<Mutex>::operator=(
ProxyLockableUniqueLock&& other) noexcept {
proxy_ = std::move(other.proxy_);
mutex_ = exchange(other.mutex_, nullptr);
mutex_ = std::exchange(other.mutex_, nullptr);
return *this;
}
......
......@@ -21,6 +21,8 @@
#include <folly/Utility.h>
#include <folly/portability/GTest.h>
#include <utility>
namespace folly {
namespace {
......@@ -104,13 +106,13 @@ class Atomic {
Integer value,
std::memory_order = std::memory_order_seq_cst) {
onFetchOr_();
return exchange(integer_, integer_ | value);
return std::exchange(integer_, integer_ | value);
}
Integer fetch_and(
Integer value,
std::memory_order = std::memory_order_seq_cst) {
onFetchAnd_();
return exchange(integer_, integer_ & value);
return std::exchange(integer_, integer_ & value);
}
Integer load(std::memory_order = std::memory_order_seq_cst) {
......
......@@ -90,13 +90,6 @@ TEST_F(UtilityTest, forward_like) {
EXPECT_EQ(&x, std::addressof(as_mutable(folly::forward_like<char const>(x))));
}
TEST_F(UtilityTest, exchange) {
auto obj = std::map<std::string, int>{{"hello", 3}};
auto old = exchange(obj, {{"world", 4}});
EXPECT_EQ((std::map<std::string, int>{{"world", 4}}), obj);
EXPECT_EQ((std::map<std::string, int>{{"hello", 3}}), old);
}
TEST(FollyIntegerSequence, core) {
constexpr auto seq = folly::integer_sequence<int, 0, 3, 2>();
static_assert(seq.size() == 3, "");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment