Commit 43a532fc authored by Igor Sheludko's avatar Igor Sheludko Committed by Commit Bot

[cleanup] Templatize AsAtomicWordX and AsAtomicPointer definitions

Bug: v8:8238
Change-Id: I7fa1538909bfaf368498ebcc1c59eed258e81a16
Reviewed-on: https://chromium-review.googlesource.com/c/1352272Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57877}
parent 535542a8
...@@ -58,122 +58,57 @@ class AtomicValue { ...@@ -58,122 +58,57 @@ class AtomicValue {
base::AtomicWord value_; base::AtomicWord value_;
}; };
class AsAtomic32 { // Provides atomic operations for a values stored at some address.
template <typename TAtomicStorageType>
class AsAtomicImpl {
public: public:
template <typename T> using AtomicStorageType = TAtomicStorageType;
static T Acquire_Load(T* addr) {
STATIC_ASSERT(sizeof(T) <= sizeof(base::Atomic32));
return to_return_type<T>(base::Acquire_Load(to_storage_addr(addr)));
}
template <typename T>
static T Relaxed_Load(T* addr) {
STATIC_ASSERT(sizeof(T) <= sizeof(base::Atomic32));
return to_return_type<T>(base::Relaxed_Load(to_storage_addr(addr)));
}
template <typename T>
static void Release_Store(T* addr,
typename std::remove_reference<T>::type new_value) {
STATIC_ASSERT(sizeof(T) <= sizeof(base::Atomic32));
base::Release_Store(to_storage_addr(addr), to_storage_type(new_value));
}
template <typename T>
static void Relaxed_Store(T* addr,
typename std::remove_reference<T>::type new_value) {
STATIC_ASSERT(sizeof(T) <= sizeof(base::Atomic32));
base::Relaxed_Store(to_storage_addr(addr), to_storage_type(new_value));
}
template <typename T>
static T Release_CompareAndSwap(
T* addr, typename std::remove_reference<T>::type old_value,
typename std::remove_reference<T>::type new_value) {
STATIC_ASSERT(sizeof(T) <= sizeof(base::Atomic32));
return to_return_type<T>(base::Release_CompareAndSwap(
to_storage_addr(addr), to_storage_type(old_value),
to_storage_type(new_value)));
}
// Atomically sets bits selected by the mask to the given value.
// Returns false if the bits are already set as needed.
template <typename T>
static bool SetBits(T* addr, T bits, T mask) {
STATIC_ASSERT(sizeof(T) <= sizeof(base::Atomic32));
DCHECK_EQ(bits & ~mask, static_cast<T>(0));
T old_value;
T new_value;
do {
old_value = Relaxed_Load(addr);
if ((old_value & mask) == bits) return false;
new_value = (old_value & ~mask) | bits;
} while (Release_CompareAndSwap(addr, old_value, new_value) != old_value);
return true;
}
private:
template <typename T>
static base::Atomic32 to_storage_type(T value) {
return static_cast<base::Atomic32>(value);
}
template <typename T>
static T to_return_type(base::Atomic32 value) {
return static_cast<T>(value);
}
template <typename T>
static base::Atomic32* to_storage_addr(T* value) {
return reinterpret_cast<base::Atomic32*>(value);
}
template <typename T>
static const base::Atomic32* to_storage_addr(const T* value) {
return reinterpret_cast<const base::Atomic32*>(value);
}
};
class AsAtomicWord {
public:
template <typename T> template <typename T>
static T Acquire_Load(T* addr) { static T Acquire_Load(T* addr) {
STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord)); STATIC_ASSERT(sizeof(T) <= sizeof(AtomicStorageType));
return to_return_type<T>(base::Acquire_Load(to_storage_addr(addr))); return cast_helper<T>::to_return_type(
base::Acquire_Load(to_storage_addr(addr)));
} }
template <typename T> template <typename T>
static T Relaxed_Load(T* addr) { static T Relaxed_Load(T* addr) {
STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord)); STATIC_ASSERT(sizeof(T) <= sizeof(AtomicStorageType));
return to_return_type<T>(base::Relaxed_Load(to_storage_addr(addr))); return cast_helper<T>::to_return_type(
base::Relaxed_Load(to_storage_addr(addr)));
} }
template <typename T> template <typename T>
static void Release_Store(T* addr, static void Release_Store(T* addr,
typename std::remove_reference<T>::type new_value) { typename std::remove_reference<T>::type new_value) {
STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord)); STATIC_ASSERT(sizeof(T) <= sizeof(AtomicStorageType));
base::Release_Store(to_storage_addr(addr), to_storage_type(new_value)); base::Release_Store(to_storage_addr(addr),
cast_helper<T>::to_storage_type(new_value));
} }
template <typename T> template <typename T>
static void Relaxed_Store(T* addr, static void Relaxed_Store(T* addr,
typename std::remove_reference<T>::type new_value) { typename std::remove_reference<T>::type new_value) {
STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord)); STATIC_ASSERT(sizeof(T) <= sizeof(AtomicStorageType));
base::Relaxed_Store(to_storage_addr(addr), to_storage_type(new_value)); base::Relaxed_Store(to_storage_addr(addr),
cast_helper<T>::to_storage_type(new_value));
} }
template <typename T> template <typename T>
static T Release_CompareAndSwap( static T Release_CompareAndSwap(
T* addr, typename std::remove_reference<T>::type old_value, T* addr, typename std::remove_reference<T>::type old_value,
typename std::remove_reference<T>::type new_value) { typename std::remove_reference<T>::type new_value) {
STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord)); STATIC_ASSERT(sizeof(T) <= sizeof(AtomicStorageType));
return to_return_type<T>(base::Release_CompareAndSwap( return cast_helper<T>::to_return_type(base::Release_CompareAndSwap(
to_storage_addr(addr), to_storage_type(old_value), to_storage_addr(addr), cast_helper<T>::to_storage_type(old_value),
to_storage_type(new_value))); cast_helper<T>::to_storage_type(new_value)));
} }
// Atomically sets bits selected by the mask to the given value. // Atomically sets bits selected by the mask to the given value.
// Returns false if the bits are already set as needed. // Returns false if the bits are already set as needed.
template <typename T> template <typename T>
static bool SetBits(T* addr, T bits, T mask) { static bool SetBits(T* addr, T bits, T mask) {
STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord)); STATIC_ASSERT(sizeof(T) <= sizeof(AtomicStorageType));
DCHECK_EQ(bits & ~mask, static_cast<T>(0)); DCHECK_EQ(bits & ~mask, static_cast<T>(0));
T old_value; T old_value;
T new_value; T new_value;
...@@ -186,138 +121,51 @@ class AsAtomicWord { ...@@ -186,138 +121,51 @@ class AsAtomicWord {
} }
private: private:
template <typename T> template <typename U>
static base::AtomicWord to_storage_type(T value) { struct cast_helper {
return static_cast<base::AtomicWord>(value); static AtomicStorageType to_storage_type(U value) {
} return static_cast<AtomicStorageType>(value);
template <typename T> }
static T to_return_type(base::AtomicWord value) { static U to_return_type(AtomicStorageType value) {
return static_cast<T>(value); return static_cast<U>(value);
} }
template <typename T> };
static base::AtomicWord* to_storage_addr(T* value) {
return reinterpret_cast<base::AtomicWord*>(value);
}
template <typename T>
static const base::AtomicWord* to_storage_addr(const T* value) {
return reinterpret_cast<const base::AtomicWord*>(value);
}
};
class AsAtomic8 {
public:
template <typename T>
static T Acquire_Load(T* addr) {
STATIC_ASSERT(sizeof(T) <= sizeof(base::Atomic8));
return to_return_type<T>(base::Acquire_Load(to_storage_addr(addr)));
}
template <typename T>
static T Relaxed_Load(T* addr) {
STATIC_ASSERT(sizeof(T) <= sizeof(base::Atomic8));
return to_return_type<T>(base::Relaxed_Load(to_storage_addr(addr)));
}
template <typename T>
static void Release_Store(T* addr,
typename std::remove_reference<T>::type new_value) {
STATIC_ASSERT(sizeof(T) <= sizeof(base::Atomic8));
base::Release_Store(to_storage_addr(addr), to_storage_type(new_value));
}
template <typename T>
static void Relaxed_Store(T* addr,
typename std::remove_reference<T>::type new_value) {
STATIC_ASSERT(sizeof(T) <= sizeof(base::Atomic8));
base::Relaxed_Store(to_storage_addr(addr), to_storage_type(new_value));
}
template <typename T> template <typename U>
static T Release_CompareAndSwap( struct cast_helper<U*> {
T* addr, typename std::remove_reference<T>::type old_value, static AtomicStorageType to_storage_type(U* value) {
typename std::remove_reference<T>::type new_value) { return reinterpret_cast<AtomicStorageType>(value);
STATIC_ASSERT(sizeof(T) <= sizeof(base::Atomic8)); }
return to_return_type<T>(base::Release_CompareAndSwap( static U* to_return_type(AtomicStorageType value) {
to_storage_addr(addr), to_storage_type(old_value), return reinterpret_cast<U*>(value);
to_storage_type(new_value))); }
} };
private:
template <typename T>
static base::Atomic8 to_storage_type(T value) {
return static_cast<base::Atomic8>(value);
}
template <typename T> template <typename T>
static T to_return_type(base::Atomic8 value) { static AtomicStorageType* to_storage_addr(T* value) {
return static_cast<T>(value); return reinterpret_cast<AtomicStorageType*>(value);
} }
template <typename T> template <typename T>
static base::Atomic8* to_storage_addr(T* value) { static const AtomicStorageType* to_storage_addr(const T* value) {
return reinterpret_cast<base::Atomic8*>(value); return reinterpret_cast<const AtomicStorageType*>(value);
}
template <typename T>
static const base::Atomic8* to_storage_addr(const T* value) {
return reinterpret_cast<const base::Atomic8*>(value);
} }
}; };
class AsAtomicPointer { using AsAtomic8 = AsAtomicImpl<base::Atomic8>;
public: using AsAtomic32 = AsAtomicImpl<base::Atomic32>;
template <typename T> using AsAtomicWord = AsAtomicImpl<base::AtomicWord>;
static T Acquire_Load(T* addr) {
STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord));
return to_return_type<T>(base::Acquire_Load(to_storage_addr(addr)));
}
template <typename T>
static T Relaxed_Load(T* addr) {
STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord));
return to_return_type<T>(base::Relaxed_Load(to_storage_addr(addr)));
}
template <typename T>
static void Release_Store(T* addr,
typename std::remove_reference<T>::type new_value) {
STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord));
base::Release_Store(to_storage_addr(addr), to_storage_type(new_value));
}
template <typename T>
static void Relaxed_Store(T* addr,
typename std::remove_reference<T>::type new_value) {
STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord));
base::Relaxed_Store(to_storage_addr(addr), to_storage_type(new_value));
}
template <typename T>
static T Release_CompareAndSwap(
T* addr, typename std::remove_reference<T>::type old_value,
typename std::remove_reference<T>::type new_value) {
STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord));
return to_return_type<T>(base::Release_CompareAndSwap(
to_storage_addr(addr), to_storage_type(old_value),
to_storage_type(new_value)));
}
private: // This is similar to AsAtomicWord but it explicitly deletes functionality
template <typename T> // provided atomic access to bit representation of stored values.
static base::AtomicWord to_storage_type(T value) { template <typename TAtomicStorageType>
return reinterpret_cast<base::AtomicWord>(value); class AsAtomicPointerImpl : public AsAtomicImpl<TAtomicStorageType> {
} public:
template <typename T>
static T to_return_type(base::AtomicWord value) {
return reinterpret_cast<T>(value);
}
template <typename T>
static base::AtomicWord* to_storage_addr(T* value) {
return reinterpret_cast<base::AtomicWord*>(value);
}
template <typename T> template <typename T>
static const base::AtomicWord* to_storage_addr(const T* value) { static bool SetBits(T* addr, T bits, T mask) = delete;
return reinterpret_cast<const base::AtomicWord*>(value);
}
}; };
using AsAtomicPointer = AsAtomicPointerImpl<base::AtomicWord>;
template <typename T, template <typename T,
typename = typename std::enable_if<std::is_unsigned<T>::value>::type> typename = typename std::enable_if<std::is_unsigned<T>::value>::type>
inline void CheckedIncrement(std::atomic<T>* number, T amount) { inline void CheckedIncrement(std::atomic<T>* number, T amount) {
......
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