blob: 7e13601af9e1187ecd253e98d05f58ded21c0849 [file] [log] [blame]
Mathieu Chartiereb8167a2014-05-07 15:43:14 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ART_RUNTIME_HANDLE_H_
18#define ART_RUNTIME_HANDLE_H_
19
20#include "base/casts.h"
21#include "base/logging.h"
22#include "base/macros.h"
23#include "stack.h"
24
25namespace art {
26
27class Thread;
28
Mathieu Chartierbfd9a432014-05-21 17:43:44 -070029template<class T> class Handle;
30
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070031template<class T>
Mathieu Chartierbfd9a432014-05-21 17:43:44 -070032class ConstHandle {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070033 public:
Mathieu Chartierbfd9a432014-05-21 17:43:44 -070034 ConstHandle() : reference_(nullptr) {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070035 }
Mathieu Chartierbfd9a432014-05-21 17:43:44 -070036 ConstHandle(const ConstHandle<T>& handle) ALWAYS_INLINE : reference_(handle.reference_) {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070037 }
Mathieu Chartierbfd9a432014-05-21 17:43:44 -070038 ConstHandle<T>& operator=(const ConstHandle<T>& handle) ALWAYS_INLINE {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070039 reference_ = handle.reference_;
40 return *this;
41 }
Mathieu Chartierbfd9a432014-05-21 17:43:44 -070042 explicit ConstHandle(StackReference<T>* reference) ALWAYS_INLINE : reference_(reference) {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070043 }
44 T& operator*() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE {
45 return *Get();
46 }
47 T* operator->() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE {
48 return Get();
49 }
50 T* Get() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE {
51 return reference_->AsMirrorPtr();
52 }
Mathieu Chartier0cd81352014-05-22 16:48:55 -070053 jobject ToJObject() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE {
54 if (UNLIKELY(reference_->AsMirrorPtr() == nullptr)) {
55 // Special case so that we work with NullHandles.
56 return nullptr;
57 }
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070058 return reinterpret_cast<jobject>(reference_);
59 }
60
Mathieu Chartier0cd81352014-05-22 16:48:55 -070061 protected:
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070062 StackReference<T>* reference_;
63
64 template<typename S>
Mathieu Chartierbfd9a432014-05-21 17:43:44 -070065 explicit ConstHandle(StackReference<S>* reference)
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070066 : reference_(reinterpret_cast<StackReference<T>*>(reference)) {
67 }
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070068 template<typename S>
Mathieu Chartierbfd9a432014-05-21 17:43:44 -070069 explicit ConstHandle(const ConstHandle<S>& handle)
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070070 : reference_(reinterpret_cast<StackReference<T>*>(handle.reference_)) {
71 }
72
Mathieu Chartier0cd81352014-05-22 16:48:55 -070073 StackReference<T>* GetReference() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE {
74 return reference_;
75 }
Mathieu Chartierbfd9a432014-05-21 17:43:44 -070076 const StackReference<T>* GetReference() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
77 ALWAYS_INLINE {
78 return reference_;
79 }
80
81 private:
82 friend class BuildGenericJniFrameVisitor;
83 template<class S> friend class ConstHandle;
84 friend class HandleScope;
85 template<class S> friend class HandleWrapper;
86 template<size_t kNumReferences> friend class StackHandleScope;
87};
88
89template<class T>
90class Handle : public ConstHandle<T> {
91 public:
92 Handle() {
93 }
94 Handle(const Handle<T>& handle) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE
95 : ConstHandle<T>(handle.reference_) {
96 }
97 Handle<T>& operator=(const Handle<T>& handle) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
98 ALWAYS_INLINE {
99 ConstHandle<T>::operator=(handle);
100 return *this;
101 }
102 explicit Handle(StackReference<T>* reference) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
103 ALWAYS_INLINE : ConstHandle<T>(reference) {
104 }
105 T* Assign(T* reference) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE {
106 StackReference<T>* ref = ConstHandle<T>::GetReference();
107 T* const old = ref->AsMirrorPtr();
108 ref->Assign(reference);
109 return old;
110 }
111
112 protected:
113 template<typename S>
114 explicit Handle(StackReference<S>* reference) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
115 : ConstHandle<T>(reference) {
116 }
117 template<typename S>
118 explicit Handle(const Handle<S>& handle) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
119 : ConstHandle<T>(handle) {
120 }
Mathieu Chartier0cd81352014-05-22 16:48:55 -0700121
122 private:
123 friend class BuildGenericJniFrameVisitor;
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700124 template<class S> friend class Handle;
125 friend class HandleScope;
126 template<class S> friend class HandleWrapper;
127 template<size_t kNumReferences> friend class StackHandleScope;
128};
129
Mathieu Chartier0cd81352014-05-22 16:48:55 -0700130template<class T>
131class NullHandle : public Handle<T> {
132 public:
133 NullHandle() : Handle<T>(&null_ref_) {
134 }
135
136 private:
137 StackReference<T> null_ref_;
138};
139
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700140} // namespace art
141
142#endif // ART_RUNTIME_HANDLE_H_