// 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_BASE_ATOMIC_UTILS_H_
#define V8_BASE_ATOMIC_UTILS_H_

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

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

namespace v8 {
namespace base {

// Deprecated. Use std::atomic<T> for new code.
// 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 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_;
};

// Provides atomic operations for a values stored at some address.
template <typename TAtomicStorageType>
class AsAtomicImpl {
 public:
  using AtomicStorageType = TAtomicStorageType;

  template <typename T>
  static T Acquire_Load(T* addr) {
    STATIC_ASSERT(sizeof(T) <= sizeof(AtomicStorageType));
    return cast_helper<T>::to_return_type(
        base::Acquire_Load(to_storage_addr(addr)));
  }

  template <typename T>
  static T Relaxed_Load(T* addr) {
    STATIC_ASSERT(sizeof(T) <= sizeof(AtomicStorageType));
    return cast_helper<T>::to_return_type(
        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(AtomicStorageType));
    base::Release_Store(to_storage_addr(addr),
                        cast_helper<T>::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(AtomicStorageType));
    base::Relaxed_Store(to_storage_addr(addr),
                        cast_helper<T>::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(AtomicStorageType));
    return cast_helper<T>::to_return_type(base::Release_CompareAndSwap(
        to_storage_addr(addr), cast_helper<T>::to_storage_type(old_value),
        cast_helper<T>::to_storage_type(new_value)));
  }

  template <typename T>
  static T Relaxed_CompareAndSwap(
      T* addr, typename std::remove_reference<T>::type old_value,
      typename std::remove_reference<T>::type new_value) {
    STATIC_ASSERT(sizeof(T) <= sizeof(AtomicStorageType));
    return cast_helper<T>::to_return_type(base::Relaxed_CompareAndSwap(
        to_storage_addr(addr), cast_helper<T>::to_storage_type(old_value),
        cast_helper<T>::to_storage_type(new_value)));
  }

  template <typename T>
  static T AcquireRelease_CompareAndSwap(
      T* addr, typename std::remove_reference<T>::type old_value,
      typename std::remove_reference<T>::type new_value) {
    STATIC_ASSERT(sizeof(T) <= sizeof(AtomicStorageType));
    return cast_helper<T>::to_return_type(base::AcquireRelease_CompareAndSwap(
        to_storage_addr(addr), cast_helper<T>::to_storage_type(old_value),
        cast_helper<T>::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(AtomicStorageType));
    DCHECK_EQ(bits & ~mask, static_cast<T>(0));
    T old_value = Relaxed_Load(addr);
    T new_value, old_value_before_cas;
    do {
      if ((old_value & mask) == bits) return false;
      new_value = (old_value & ~mask) | bits;
      old_value_before_cas = old_value;
      old_value = Release_CompareAndSwap(addr, old_value, new_value);
    } while (old_value != old_value_before_cas);
    return true;
  }

 private:
  template <typename U>
  struct cast_helper {
    static AtomicStorageType to_storage_type(U value) {
      return static_cast<AtomicStorageType>(value);
    }
    static U to_return_type(AtomicStorageType value) {
      return static_cast<U>(value);
    }
  };

  template <typename U>
  struct cast_helper<U*> {
    static AtomicStorageType to_storage_type(U* value) {
      return reinterpret_cast<AtomicStorageType>(value);
    }
    static U* to_return_type(AtomicStorageType value) {
      return reinterpret_cast<U*>(value);
    }
  };

  template <typename T>
  static AtomicStorageType* to_storage_addr(T* value) {
    return reinterpret_cast<AtomicStorageType*>(value);
  }
  template <typename T>
  static const AtomicStorageType* to_storage_addr(const T* value) {
    return reinterpret_cast<const AtomicStorageType*>(value);
  }
};

using AsAtomic8 = AsAtomicImpl<base::Atomic8>;
using AsAtomic32 = AsAtomicImpl<base::Atomic32>;
using AsAtomicWord = AsAtomicImpl<base::AtomicWord>;

// This is similar to AsAtomicWord but it explicitly deletes functionality
// provided atomic access to bit representation of stored values.
template <typename TAtomicStorageType>
class AsAtomicPointerImpl : public AsAtomicImpl<TAtomicStorageType> {
 public:
  template <typename T>
  static bool SetBits(T* addr, T bits, T mask) = delete;
};

using AsAtomicPointer = AsAtomicPointerImpl<base::AtomicWord>;

template <typename T,
          typename = typename std::enable_if<std::is_unsigned<T>::value>::type>
inline void CheckedIncrement(std::atomic<T>* number, T amount) {
  const T old = number->fetch_add(amount);
  DCHECK_GE(old + amount, old);
  USE(old);
}

template <typename T,
          typename = typename std::enable_if<std::is_unsigned<T>::value>::type>
inline void CheckedDecrement(std::atomic<T>* number, T amount) {
  const T old = number->fetch_sub(amount);
  DCHECK_GE(old, amount);
  USE(old);
}

template <typename T>
V8_INLINE std::atomic<T>* AsAtomicPtr(T* t) {
  return reinterpret_cast<std::atomic<T>*>(t);
}

template <typename T>
V8_INLINE const std::atomic<T>* AsAtomicPtr(const T* t) {
  return reinterpret_cast<const std::atomic<T>*>(t);
}

}  // namespace base
}  // namespace v8

#endif  // V8_BASE_ATOMIC_UTILS_H_
