/* * 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 "stack.h" namespace art { class Thread; template class Handle; template class ConstHandle { public: ConstHandle() : reference_(nullptr) { } ConstHandle(const ConstHandle& handle) ALWAYS_INLINE : reference_(handle.reference_) { } ConstHandle& operator=(const ConstHandle& handle) ALWAYS_INLINE { reference_ = handle.reference_; return *this; } explicit ConstHandle(StackReference* reference) ALWAYS_INLINE : reference_(reference) { } T& operator*() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE { return *Get(); } T* operator->() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE { return Get(); } T* Get() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE { return reference_->AsMirrorPtr(); } jobject ToJObject() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE { if (UNLIKELY(reference_->AsMirrorPtr() == nullptr)) { // Special case so that we work with NullHandles. return nullptr; } return reinterpret_cast(reference_); } protected: StackReference* reference_; template explicit ConstHandle(StackReference* reference) : reference_(reinterpret_cast*>(reference)) { } template explicit ConstHandle(const ConstHandle& handle) : reference_(reinterpret_cast*>(handle.reference_)) { } StackReference* GetReference() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE { return reference_; } const StackReference* GetReference() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE { return reference_; } private: friend class BuildGenericJniFrameVisitor; template friend class ConstHandle; friend class HandleScope; template friend class HandleWrapper; template friend class StackHandleScope; }; template class Handle : public ConstHandle { public: Handle() { } Handle(const Handle& handle) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE : ConstHandle(handle.reference_) { } Handle& operator=(const Handle& handle) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE { ConstHandle::operator=(handle); return *this; } explicit Handle(StackReference* reference) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE : ConstHandle(reference) { } T* Assign(T* reference) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE { StackReference* ref = ConstHandle::GetReference(); T* const old = ref->AsMirrorPtr(); ref->Assign(reference); return old; } protected: template explicit Handle(StackReference* reference) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : ConstHandle(reference) { } template explicit Handle(const Handle& handle) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : ConstHandle(handle) { } private: friend class BuildGenericJniFrameVisitor; template friend class Handle; friend class HandleScope; template friend class HandleWrapper; template friend class StackHandleScope; }; template class NullHandle : public Handle { public: NullHandle() : Handle(&null_ref_) { } private: StackReference null_ref_; }; } // namespace art #endif // ART_RUNTIME_HANDLE_H_