// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_ATOMIC_UTILS_H_
#define V8_ATOMIC_UTILS_H_

#include <limits.h>
#include <type_traits>

#include "src/base/atomicops.h"
#include "src/base/macros.h"

namespace v8 {
namespace base {

template <class T>
class AtomicNumber {
 public:
  AtomicNumber() : value_(0) {}
  explicit AtomicNumber(T initial) : value_(initial) {}

  // Returns the value after incrementing.
  V8_INLINE T Increment(T increment) {
    return static_cast<T>(base::Barrier_AtomicIncrement(
        &value_, static_cast<base::AtomicWord>(increment)));
  }

  // Returns the value after decrementing.
  V8_INLINE T Decrement(T decrement) {
    return static_cast<T>(base::Barrier_AtomicIncrement(
        &value_, -static_cast<base::AtomicWord>(decrement)));
  }

  V8_INLINE T Value() const {
    return static_cast<T>(base::Acquire_Load(&value_));
  }

  V8_INLINE void SetValue(T new_value) {
    base::Release_Store(&value_, static_cast<base::AtomicWord>(new_value));
  }

  V8_INLINE T operator=(T value) {
    SetValue(value);
    return value;
  }

  V8_INLINE T operator+=(T value) { return Increment(value); }
  V8_INLINE T operator-=(T value) { return Decrement(value); }

 private:
  STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord));

  base::AtomicWord value_;
};

// Flag using T atomically. Also accepts void* as T.
template <typename T>
class AtomicValue {
 public:
  AtomicValue() : value_(0) {}

  explicit AtomicValue(T initial)
      : value_(cast_helper<T>::to_storage_type(initial)) {}

  V8_INLINE T Value() const {
    return cast_helper<T>::to_return_type(base::Acquire_Load(&value_));
  }

  V8_INLINE bool TrySetValue(T old_value, T new_value) {
    return base::Release_CompareAndSwap(
               &value_, cast_helper<T>::to_storage_type(old_value),
               cast_helper<T>::to_storage_type(new_value)) ==
           cast_helper<T>::to_storage_type(old_value);
  }

  V8_INLINE void SetBits(T bits, T mask) {
    DCHECK_EQ(bits & ~mask, static_cast<T>(0));
    T old_value;
    T new_value;
    do {
      old_value = Value();
      new_value = (old_value & ~mask) | bits;
    } while (!TrySetValue(old_value, new_value));
  }

  V8_INLINE void SetBit(int bit) {
    SetBits(static_cast<T>(1) << bit, static_cast<T>(1) << bit);
  }

  V8_INLINE void ClearBit(int bit) { SetBits(0, 1 << bit); }

  V8_INLINE void SetValue(T new_value) {
    base::Release_Store(&value_, cast_helper<T>::to_storage_type(new_value));
  }

 private:
  STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord));

  template <typename S>
  struct cast_helper {
    static base::AtomicWord to_storage_type(S value) {
      return static_cast<base::AtomicWord>(value);
    }
    static S to_return_type(base::AtomicWord value) {
      return static_cast<S>(value);
    }
  };

  template <typename S>
  struct cast_helper<S*> {
    static base::AtomicWord to_storage_type(S* value) {
      return reinterpret_cast<base::AtomicWord>(value);
    }
    static S* to_return_type(base::AtomicWord value) {
      return reinterpret_cast<S*>(value);
    }
  };

  base::AtomicWord value_;
};

class AsAtomic32 {
 public:
  template <typename T>
  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>
  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)));
  }

  // 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::AtomicWord));
    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::AtomicWord to_storage_type(T value) {
    return static_cast<base::AtomicWord>(value);
  }
  template <typename T>
  static T to_return_type(base::AtomicWord value) {
    return static_cast<T>(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>
  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::Atomic8));
    return to_return_type<T>(base::Release_CompareAndSwap(
        to_storage_addr(addr), to_storage_type(old_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>
  static T to_return_type(base::Atomic8 value) {
    return static_cast<T>(value);
  }
  template <typename T>
  static base::Atomic8* to_storage_addr(T* value) {
    return reinterpret_cast<base::Atomic8*>(value);
  }
  template <typename T>
  static const base::Atomic8* to_storage_addr(const T* value) {
    return reinterpret_cast<const base::Atomic8*>(value);
  }
};

class AsAtomicPointer {
 public:
  template <typename T>
  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:
  template <typename T>
  static base::AtomicWord to_storage_type(T value) {
    return reinterpret_cast<base::AtomicWord>(value);
  }
  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>
  static const base::AtomicWord* to_storage_addr(const T* value) {
    return reinterpret_cast<const base::AtomicWord*>(value);
  }
};

// This class is intended to be used as a wrapper for elements of an array
// that is passed in to STL functions such as std::sort. It ensures that
// elements accesses are atomic.
// Usage example:
//   Object** given_array;
//   AtomicElement<Object*>* wrapped =
//       reinterpret_cast<AtomicElement<Object*>(given_array);
//   std::sort(wrapped, wrapped + given_length, cmp);
// where the cmp function uses the value() accessor to compare the elements.
template <typename T>
class AtomicElement {
 public:
  AtomicElement(const AtomicElement<T>& other) {
    AsAtomicPointer::Relaxed_Store(
        &value_, AsAtomicPointer::Relaxed_Load(&other.value_));
  }

  void operator=(const AtomicElement<T>& other) {
    AsAtomicPointer::Relaxed_Store(
        &value_, AsAtomicPointer::Relaxed_Load(&other.value_));
  }

  T value() const { return AsAtomicPointer::Relaxed_Load(&value_); }

  bool operator<(const AtomicElement<T>& other) const {
    return value() < other.value();
  }

  bool operator==(const AtomicElement<T>& other) const {
    return value() == other.value();
  }

 private:
  T value_;
};

}  // namespace base
}  // namespace v8

#endif  // #define V8_ATOMIC_UTILS_H_
