// 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 "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() { 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_;
};

// This type uses no barrier accessors to change atomic word. Be careful with
// data races.
template <typename T>
class NoBarrierAtomicValue {
 public:
  NoBarrierAtomicValue() : value_(0) {}

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

  static NoBarrierAtomicValue* FromAddress(void* address) {
    return reinterpret_cast<base::NoBarrierAtomicValue<T>*>(address);
  }

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

  V8_INLINE void SetValue(T new_value) {
    base::NoBarrier_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_;
};

// 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, 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_;
};


// See utils.h for EnumSet. Storage is always base::AtomicWord.
// Requirements on E:
// - No explicit values.
// - E::kLastValue defined to be the last actually used value.
//
// Example:
// enum E { kA, kB, kC, kLastValue = kC };
template <class E>
class AtomicEnumSet {
 public:
  explicit AtomicEnumSet(base::AtomicWord bits = 0) : bits_(bits) {}

  bool IsEmpty() const { return ToIntegral() == 0; }

  bool Contains(E element) const { return (ToIntegral() & Mask(element)) != 0; }
  bool ContainsAnyOf(const AtomicEnumSet& set) const {
    return (ToIntegral() & set.ToIntegral()) != 0;
  }

  void RemoveAll() { base::Release_Store(&bits_, 0); }

  bool operator==(const AtomicEnumSet& set) const {
    return ToIntegral() == set.ToIntegral();
  }

  bool operator!=(const AtomicEnumSet& set) const {
    return ToIntegral() != set.ToIntegral();
  }

  AtomicEnumSet<E> operator|(const AtomicEnumSet& set) const {
    return AtomicEnumSet<E>(ToIntegral() | set.ToIntegral());
  }

// The following operations modify the underlying storage.

#define ATOMIC_SET_WRITE(OP, NEW_VAL)                                     \
  do {                                                                    \
    base::AtomicWord old;                                                 \
    do {                                                                  \
      old = base::Acquire_Load(&bits_);                                   \
    } while (base::Release_CompareAndSwap(&bits_, old, old OP NEW_VAL) != \
             old);                                                        \
  } while (false)

  void Add(E element) { ATOMIC_SET_WRITE(|, Mask(element)); }

  void Add(const AtomicEnumSet& set) { ATOMIC_SET_WRITE(|, set.ToIntegral()); }

  void Remove(E element) { ATOMIC_SET_WRITE(&, ~Mask(element)); }

  void Remove(const AtomicEnumSet& set) {
    ATOMIC_SET_WRITE(&, ~set.ToIntegral());
  }

  void Intersect(const AtomicEnumSet& set) {
    ATOMIC_SET_WRITE(&, set.ToIntegral());
  }

#undef ATOMIC_SET_OP

 private:
  // Check whether there's enough storage to hold E.
  STATIC_ASSERT(E::kLastValue < (sizeof(base::AtomicWord) * CHAR_BIT));

  V8_INLINE base::AtomicWord ToIntegral() const {
    return base::Acquire_Load(&bits_);
  }

  V8_INLINE base::AtomicWord Mask(E element) const {
    return static_cast<base::AtomicWord>(1) << element;
  }

  base::AtomicWord bits_;
};

}  // namespace base
}  // namespace v8

#endif  // #define V8_ATOMIC_UTILS_H_
