/*
 * Copyright (C) 2012 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_SCOPED_THREAD_STATE_CHANGE_INL_H_
#define ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_INL_H_

#include "scoped_thread_state_change.h"

#include <android-base/logging.h>

#include "base/casts.h"
#include "base/mutex.h"
#include "jni/jni_env_ext-inl.h"
#include "obj_ptr-inl.h"
#include "runtime.h"
#include "thread-inl.h"

namespace art {

inline ScopedThreadStateChange::ScopedThreadStateChange(Thread* self, ThreadState new_thread_state)
    : self_(self), thread_state_(new_thread_state), expected_has_no_thread_(false) {
  if (UNLIKELY(self_ == nullptr)) {
    // Value chosen arbitrarily and won't be used in the destructor since thread_ == null.
    old_thread_state_ = ThreadState::kTerminated;
    Runtime* runtime = Runtime::Current();
    CHECK(runtime == nullptr || !runtime->IsStarted() || runtime->IsShuttingDown(self_));
  } else {
    DCHECK_EQ(self, Thread::Current());
    // Read state without locks, ok as state is effectively thread local and we're not interested
    // in the suspend count (this will be handled in the runnable transitions).
    old_thread_state_ = self->GetState();
    if (old_thread_state_ != new_thread_state) {
      if (new_thread_state == ThreadState::kRunnable) {
        self_->TransitionFromSuspendedToRunnable();
      } else if (old_thread_state_ == ThreadState::kRunnable) {
        self_->TransitionFromRunnableToSuspended(new_thread_state);
      } else {
        // A suspended transition to another effectively suspended transition, ok to use Unsafe.
        self_->SetState(new_thread_state);
      }
    }
  }
}

inline ScopedThreadStateChange::~ScopedThreadStateChange() {
  if (UNLIKELY(self_ == nullptr)) {
    ScopedThreadChangeDestructorCheck();
  } else {
    if (old_thread_state_ != thread_state_) {
      if (old_thread_state_ == ThreadState::kRunnable) {
        self_->TransitionFromSuspendedToRunnable();
      } else if (thread_state_ == ThreadState::kRunnable) {
        self_->TransitionFromRunnableToSuspended(old_thread_state_);
      } else {
        // A suspended transition to another effectively suspended transition, ok to use Unsafe.
        self_->SetState(old_thread_state_);
      }
    }
  }
}

template<typename T>
inline T ScopedObjectAccessAlreadyRunnable::AddLocalReference(ObjPtr<mirror::Object> obj) const {
  Locks::mutator_lock_->AssertSharedHeld(Self());
  if (kIsDebugBuild) {
    CHECK(IsRunnable());  // Don't work with raw objects in non-runnable states.
    DCheckObjIsNotClearedJniWeakGlobal(obj);
  }
  return obj == nullptr ? nullptr : Env()->AddLocalReference<T>(obj);
}

template<typename T>
inline ObjPtr<T> ScopedObjectAccessAlreadyRunnable::Decode(jobject obj) const {
  Locks::mutator_lock_->AssertSharedHeld(Self());
  DCHECK(IsRunnable());  // Don't work with raw objects in non-runnable states.
  return ObjPtr<T>::DownCast(Self()->DecodeJObject(obj));
}

inline bool ScopedObjectAccessAlreadyRunnable::IsRunnable() const {
  return self_->GetState() == ThreadState::kRunnable;
}

inline ScopedObjectAccessAlreadyRunnable::ScopedObjectAccessAlreadyRunnable(JNIEnv* env)
    : self_(ThreadForEnv(env)), env_(down_cast<JNIEnvExt*>(env)), vm_(env_->GetVm()) {}

inline ScopedObjectAccessAlreadyRunnable::ScopedObjectAccessAlreadyRunnable(Thread* self)
    : self_(self),
      env_(down_cast<JNIEnvExt*>(self->GetJniEnv())),
      vm_(env_ != nullptr ? env_->GetVm() : nullptr) {}

inline ScopedObjectAccessUnchecked::ScopedObjectAccessUnchecked(JNIEnv* env)
    : ScopedObjectAccessAlreadyRunnable(env), tsc_(Self(), ThreadState::kRunnable) {
  Self()->VerifyStack();
  Locks::mutator_lock_->AssertSharedHeld(Self());
}

inline ScopedObjectAccessUnchecked::ScopedObjectAccessUnchecked(Thread* self)
    : ScopedObjectAccessAlreadyRunnable(self), tsc_(self, ThreadState::kRunnable) {
  Self()->VerifyStack();
  Locks::mutator_lock_->AssertSharedHeld(Self());
}

inline ScopedObjectAccess::ScopedObjectAccess(JNIEnv* env) : ScopedObjectAccessUnchecked(env) {}
inline ScopedObjectAccess::ScopedObjectAccess(Thread* self) : ScopedObjectAccessUnchecked(self) {}
inline ScopedObjectAccess::~ScopedObjectAccess() {}

inline ScopedThreadSuspension::ScopedThreadSuspension(Thread* self, ThreadState suspended_state)
    : self_(self), suspended_state_(suspended_state) {
  DCHECK(self_ != nullptr);
  self_->TransitionFromRunnableToSuspended(suspended_state);
}

inline ScopedThreadSuspension::~ScopedThreadSuspension() {
  DCHECK_EQ(self_->GetState(), suspended_state_);
  self_->TransitionFromSuspendedToRunnable();
}

}  // namespace art

#endif  // ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_INL_H_
