/*
 * 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_HANDLE_H_
#define ART_RUNTIME_HANDLE_H_

#include "base/casts.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/mutex.h"
#include "base/value_object.h"
#include "jni.h"
#include "obj_ptr.h"
#include "stack_reference.h"

namespace art {

class Thread;

template<class T> class Handle;

// Handles are memory locations that contain GC roots. As the mirror::Object*s within a handle are
// GC visible then the GC may move the references within them, something that couldn't be done with
// a wrap pointer. Handles are generally allocated within HandleScopes. Handle is a super-class
// of MutableHandle and doesn't support assignment operations.
template<class T>
class Handle : public ValueObject {
 public:
  Handle() : reference_(nullptr) {
  }

  ALWAYS_INLINE Handle(const Handle<T>& handle) : reference_(handle.reference_) {
  }

  ALWAYS_INLINE Handle<T>& operator=(const Handle<T>& handle) {
    reference_ = handle.reference_;
    return *this;
  }

  ALWAYS_INLINE explicit Handle(StackReference<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 down_cast<T*>(reference_->AsMirrorPtr());
  }

  ALWAYS_INLINE jobject ToJObject() const REQUIRES_SHARED(Locks::mutator_lock_) {
    if (UNLIKELY(reference_->AsMirrorPtr() == nullptr)) {
      // Special case so that we work with null handles.
      return nullptr;
    }
    return reinterpret_cast<jobject>(reference_);
  }

  ALWAYS_INLINE StackReference<mirror::Object>* GetReference() {
    return reference_;
  }

  ALWAYS_INLINE const StackReference<mirror::Object>* GetReference() const {
    return reference_;
  }

 protected:
  template<typename S>
  explicit Handle(StackReference<S>* reference)
      : reference_(reference) {
  }
  template<typename S>
  explicit Handle(const Handle<S>& handle)
      : reference_(handle.reference_) {
  }

  StackReference<mirror::Object>* reference_;

 private:
  friend class BuildGenericJniFrameVisitor;
  template<class S> friend class Handle;
  friend class HandleScope;
  template<class S> friend class HandleWrapper;
  template<size_t kNumReferences> friend class StackHandleScope;
};

// Handles that support assignment.
template<class T>
class MutableHandle : public Handle<T> {
 public:
  MutableHandle() {
  }

  ALWAYS_INLINE MutableHandle(const MutableHandle<T>& handle)
      REQUIRES_SHARED(Locks::mutator_lock_)
      : Handle<T>(handle.reference_) {
  }

  ALWAYS_INLINE MutableHandle<T>& operator=(const MutableHandle<T>& handle)
      REQUIRES_SHARED(Locks::mutator_lock_) {
    Handle<T>::operator=(handle);
    return *this;
  }

  ALWAYS_INLINE explicit MutableHandle(StackReference<T>* reference)
      REQUIRES_SHARED(Locks::mutator_lock_)
      : Handle<T>(reference) {
  }

  ALWAYS_INLINE T* Assign(T* reference) REQUIRES_SHARED(Locks::mutator_lock_) {
    StackReference<mirror::Object>* ref = Handle<T>::GetReference();
    T* old = down_cast<T*>(ref->AsMirrorPtr());
    ref->Assign(reference);
    return old;
  }

  ALWAYS_INLINE T* Assign(ObjPtr<T> reference) REQUIRES_SHARED(Locks::mutator_lock_) {
    StackReference<mirror::Object>* ref = Handle<T>::GetReference();
    T* old = down_cast<T*>(ref->AsMirrorPtr());
    ref->Assign(reference.Ptr());
    return old;
  }


  template<typename S>
  explicit MutableHandle(const MutableHandle<S>& handle) REQUIRES_SHARED(Locks::mutator_lock_)
      : Handle<T>(handle) {
  }

  template<typename S>
  explicit MutableHandle(StackReference<S>* reference) REQUIRES_SHARED(Locks::mutator_lock_)
      : Handle<T>(reference) {
  }

 private:
  friend class BuildGenericJniFrameVisitor;
  friend class HandleScope;
  template<class S> friend class HandleWrapper;
  template<size_t kNumReferences> friend class StackHandleScope;
};

// A special case of Handle that only holds references to null. Invalid when if it goes out of
// scope. Example: Handle<T> h = ScopedNullHandle<T> will leave h being undefined.
template<class T>
class ScopedNullHandle : public Handle<T> {
 public:
  ScopedNullHandle() : Handle<T>(&null_ref_) {}

 private:
  StackReference<mirror::Object> null_ref_;
};

}  // namespace art

#endif  // ART_RUNTIME_HANDLE_H_
