/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ART_RUNTIME_REFLECTIVE_HANDLE_H_
#define ART_RUNTIME_REFLECTIVE_HANDLE_H_

#include "base/macros.h"
#include "base/value_object.h"
#include "reflective_reference.h"

namespace art HIDDEN {

// This is a holder similar to Handle<T> that is used to hold reflective references to ArtField and
// ArtMethod structures. A reflective reference is one that must be updated if the underlying class
// or instances are replaced due to structural redefinition or some other process. In general these
// don't need to be used. It's only when it's important that a reference to a field not become
// obsolete and it needs to be held over a suspend point that this should be used.
template <typename T>
class ReflectiveHandle : public ValueObject {
 public:
  static_assert(std::is_same_v<T, ArtField> || std::is_same_v<T, ArtMethod>,
                "Expected ArtField or ArtMethod");

  ReflectiveHandle() : reference_(nullptr) {}

  ALWAYS_INLINE ReflectiveHandle(const ReflectiveHandle<T>& handle) = default;
  ALWAYS_INLINE ReflectiveHandle<T>& operator=(const ReflectiveHandle<T>& handle) = default;

  ALWAYS_INLINE explicit ReflectiveHandle(ReflectiveReference<T>* reference)
      : reference_(reference) {}

  ALWAYS_INLINE T& operator*() const REQUIRES_SHARED(Locks::mutator_lock_) {
    return *Get();
  }

  ALWAYS_INLINE T* operator->() const REQUIRES_SHARED(Locks::mutator_lock_) {
    return Get();
  }

  ALWAYS_INLINE T* Get() const REQUIRES_SHARED(Locks::mutator_lock_) {
    return reference_->Ptr();
  }

  ALWAYS_INLINE bool IsNull() const {
    // It's safe to null-check it without a read barrier.
    return reference_->IsNull();
  }

  ALWAYS_INLINE bool operator!=(std::nullptr_t) const REQUIRES_SHARED(Locks::mutator_lock_) {
    return !IsNull();
  }

  ALWAYS_INLINE bool operator==(std::nullptr_t) const REQUIRES_SHARED(Locks::mutator_lock_) {
    return IsNull();
  }

 protected:
  ReflectiveReference<T>* reference_;

 private:
  friend class BaseReflectiveHandleScope;
  template <size_t kNumFieldReferences, size_t kNumMethodReferences>
  friend class StackReflectiveHandleScope;
};

// Handles that support assignment.
template <typename T>
class MutableReflectiveHandle : public ReflectiveHandle<T> {
 public:
  MutableReflectiveHandle() {}

  ALWAYS_INLINE MutableReflectiveHandle(const MutableReflectiveHandle<T>& handle) = default;

  ALWAYS_INLINE MutableReflectiveHandle<T>& operator=(const MutableReflectiveHandle<T>& handle)
      = default;

  ALWAYS_INLINE explicit MutableReflectiveHandle(ReflectiveReference<T>* reference)
      : ReflectiveHandle<T>(reference) {}

  ALWAYS_INLINE T* Assign(T* reference) REQUIRES_SHARED(Locks::mutator_lock_) {
    ReflectiveReference<T>* ref = ReflectiveHandle<T>::reference_;
    T* old = ref->Ptr();
    ref->Assign(reference);
    return old;
  }

 private:
  friend class BaseReflectiveHandleScope;
  template <size_t kNumFieldReferences, size_t kNumMethodReferences>
  friend class StackReflectiveHandleScope;
};

template<typename T>
class ReflectiveHandleWrapper : public MutableReflectiveHandle<T> {
 public:
  ReflectiveHandleWrapper(T** obj, const MutableReflectiveHandle<T>& handle)
     : MutableReflectiveHandle<T>(handle), obj_(obj) {
  }

  ReflectiveHandleWrapper(const ReflectiveHandleWrapper&) = default;

  ~ReflectiveHandleWrapper() {
    *obj_ = MutableReflectiveHandle<T>::Get();
  }

 private:
  T** const obj_;
};

}  // namespace art

#endif  // ART_RUNTIME_REFLECTIVE_HANDLE_H_
