blob: 2fd0e2cdc588daf7abee500808e39e569676f51d [file] [log] [blame]
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +01001/*
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_TRANSACTION_H_
18#define ART_RUNTIME_TRANSACTION_H_
19
20#include "base/macros.h"
21#include "base/mutex.h"
David Sehr67bf42e2018-02-26 16:43:04 -080022#include "base/safe_map.h"
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070023#include "base/value_object.h"
David Sehr9e734c72018-01-04 17:56:19 -080024#include "dex/dex_file_types.h"
David Sehr67bf42e2018-02-26 16:43:04 -080025#include "dex/primitive.h"
Mathieu Chartiere34fa1d2015-01-14 14:55:47 -080026#include "gc_root.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010027#include "offsets.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010028
29#include <list>
30#include <map>
31
32namespace art {
Vladimir Marko672c0802019-07-26 13:03:13 +010033namespace gc {
34class Heap;
35} // namespace gc
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010036namespace mirror {
37class Array;
Chang Xingcade5c32017-07-20 17:56:26 -070038class Class;
Mathieu Chartierbb816d62016-09-07 10:17:46 -070039class DexCache;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010040class Object;
41class String;
Andreas Gampedeae7db2017-05-30 09:56:41 -070042} // namespace mirror
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010043class InternTable;
Vladimir Marko672c0802019-07-26 13:03:13 +010044template<class MirrorType> class ObjPtr;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010045
Roland Levillainbbc6e7e2018-08-24 16:58:47 +010046class Transaction final {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010047 public:
Vladimir Marko0685b982021-03-25 11:59:22 +000048 static constexpr const char* kAbortExceptionDescriptor = "Ldalvik/system/TransactionAbortError;";
Sebastien Hertz2fd7e692015-04-02 11:11:19 +020049
Vladimir Marko672c0802019-07-26 13:03:13 +010050 Transaction(bool strict, mirror::Class* root);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010051 ~Transaction();
52
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010053 void Abort(const std::string& abort_message)
Mathieu Chartier90443472015-07-16 20:32:27 -070054 REQUIRES(!log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070055 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzb81e1cd2015-04-28 12:31:41 +020056 void ThrowAbortError(Thread* self, const std::string* abort_message)
Mathieu Chartier90443472015-07-16 20:32:27 -070057 REQUIRES(!log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070058 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartier90443472015-07-16 20:32:27 -070059 bool IsAborted() REQUIRES(!log_lock_);
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010060
Chang Xing605fe242017-07-20 15:57:21 -070061 // If the transaction is rollbacking. Transactions will set this flag when they start rollbacking,
62 // because the nested transaction should be disabled when rollbacking to restore the memory.
63 bool IsRollingBack();
64
Chang Xing5a906fc2017-07-26 15:01:16 -070065 // If the transaction is in strict mode, then all access of static fields will be constrained,
66 // one class's clinit will not be allowed to read or modify another class's static fields, unless
67 // the transaction is aborted.
Vladimir Marko672c0802019-07-26 13:03:13 +010068 bool IsStrict() {
Vladimir Marko4d7b6892020-01-16 17:06:35 +000069 return strict_;
Vladimir Marko672c0802019-07-26 13:03:13 +010070 }
Chang Xing5a906fc2017-07-26 15:01:16 -070071
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010072 // Record object field changes.
Mathieu Chartier38e954c2017-02-03 16:06:35 -080073 void RecordWriteFieldBoolean(mirror::Object* obj,
74 MemberOffset field_offset,
75 uint8_t value,
Fred Shih37f05ef2014-07-16 18:38:08 -070076 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070077 REQUIRES(!log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -080078 void RecordWriteFieldByte(mirror::Object* obj,
79 MemberOffset field_offset,
80 int8_t value,
Fred Shih37f05ef2014-07-16 18:38:08 -070081 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070082 REQUIRES(!log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -080083 void RecordWriteFieldChar(mirror::Object* obj,
84 MemberOffset field_offset,
85 uint16_t value,
86 bool is_volatile)
87 REQUIRES(!log_lock_);
88 void RecordWriteFieldShort(mirror::Object* obj,
89 MemberOffset field_offset,
90 int16_t value,
Fred Shih37f05ef2014-07-16 18:38:08 -070091 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070092 REQUIRES(!log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -080093 void RecordWriteField32(mirror::Object* obj,
94 MemberOffset field_offset,
95 uint32_t value,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010096 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -070097 REQUIRES(!log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -080098 void RecordWriteField64(mirror::Object* obj,
99 MemberOffset field_offset,
100 uint64_t value,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100101 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -0700102 REQUIRES(!log_lock_);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800103 void RecordWriteFieldReference(mirror::Object* obj,
104 MemberOffset field_offset,
105 mirror::Object* value,
106 bool is_volatile)
Mathieu Chartier90443472015-07-16 20:32:27 -0700107 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100108
109 // Record array change.
110 void RecordWriteArray(mirror::Array* array, size_t index, uint64_t value)
Mathieu Chartier90443472015-07-16 20:32:27 -0700111 REQUIRES(!log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700112 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100113
114 // Record intern string table changes.
Mathieu Chartier9e868092016-10-31 14:58:04 -0700115 void RecordStrongStringInsertion(ObjPtr<mirror::String> s)
Mathieu Chartier90443472015-07-16 20:32:27 -0700116 REQUIRES(Locks::intern_table_lock_)
117 REQUIRES(!log_lock_);
Mathieu Chartier9e868092016-10-31 14:58:04 -0700118 void RecordWeakStringInsertion(ObjPtr<mirror::String> s)
Mathieu Chartier90443472015-07-16 20:32:27 -0700119 REQUIRES(Locks::intern_table_lock_)
120 REQUIRES(!log_lock_);
Mathieu Chartier9e868092016-10-31 14:58:04 -0700121 void RecordStrongStringRemoval(ObjPtr<mirror::String> s)
Mathieu Chartier90443472015-07-16 20:32:27 -0700122 REQUIRES(Locks::intern_table_lock_)
123 REQUIRES(!log_lock_);
Mathieu Chartier9e868092016-10-31 14:58:04 -0700124 void RecordWeakStringRemoval(ObjPtr<mirror::String> s)
Mathieu Chartier90443472015-07-16 20:32:27 -0700125 REQUIRES(Locks::intern_table_lock_)
126 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100127
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700128 // Record resolve string.
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800129 void RecordResolveString(ObjPtr<mirror::DexCache> dex_cache, dex::StringIndex string_idx)
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700130 REQUIRES_SHARED(Locks::mutator_lock_)
131 REQUIRES(!log_lock_);
132
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100133 // Abort transaction by undoing all recorded changes.
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100134 void Rollback()
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700135 REQUIRES_SHARED(Locks::mutator_lock_)
Mathieu Chartier90443472015-07-16 20:32:27 -0700136 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100137
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700138 void VisitRoots(RootVisitor* visitor)
Mathieu Chartier90443472015-07-16 20:32:27 -0700139 REQUIRES(!log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700140 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100141
Vladimir Marko4d7b6892020-01-16 17:06:35 +0000142 bool ReadConstraint(Thread* self, ObjPtr<mirror::Object> obj)
Chang Xingbd208d82017-07-12 14:53:17 -0700143 REQUIRES(!log_lock_)
144 REQUIRES_SHARED(Locks::mutator_lock_);
145
Vladimir Marko4d7b6892020-01-16 17:06:35 +0000146 bool WriteConstraint(Thread* self, ObjPtr<mirror::Object> obj)
Chang Xingbd208d82017-07-12 14:53:17 -0700147 REQUIRES(!log_lock_)
148 REQUIRES_SHARED(Locks::mutator_lock_);
149
Vladimir Marko149cdda2019-11-12 15:02:51 +0000150 bool WriteValueConstraint(Thread* self, ObjPtr<mirror::Object> value)
151 REQUIRES(!log_lock_)
152 REQUIRES_SHARED(Locks::mutator_lock_);
153
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100154 private:
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700155 class ObjectLog : public ValueObject {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100156 public:
Fred Shih37f05ef2014-07-16 18:38:08 -0700157 void LogBooleanValue(MemberOffset offset, uint8_t value, bool is_volatile);
158 void LogByteValue(MemberOffset offset, int8_t value, bool is_volatile);
159 void LogCharValue(MemberOffset offset, uint16_t value, bool is_volatile);
160 void LogShortValue(MemberOffset offset, int16_t value, bool is_volatile);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100161 void Log32BitsValue(MemberOffset offset, uint32_t value, bool is_volatile);
162 void Log64BitsValue(MemberOffset offset, uint64_t value, bool is_volatile);
163 void LogReferenceValue(MemberOffset offset, mirror::Object* obj, bool is_volatile);
164
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800165 void Undo(mirror::Object* obj) const REQUIRES_SHARED(Locks::mutator_lock_);
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700166 void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100167
168 size_t Size() const {
169 return field_values_.size();
170 }
171
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800172 ObjectLog() = default;
173 ObjectLog(ObjectLog&& log) = default;
174
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100175 private:
176 enum FieldValueKind {
Fred Shih37f05ef2014-07-16 18:38:08 -0700177 kBoolean,
178 kByte,
179 kChar,
180 kShort,
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100181 k32Bits,
182 k64Bits,
183 kReference
184 };
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700185 struct FieldValue : public ValueObject {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100186 // TODO use JValue instead ?
187 uint64_t value;
188 FieldValueKind kind;
189 bool is_volatile;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800190
Andreas Gamped9911ee2017-03-27 13:27:24 -0700191 FieldValue() : value(0), kind(FieldValueKind::kBoolean), is_volatile(false) {}
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800192 FieldValue(FieldValue&& log) = default;
193
194 private:
195 DISALLOW_COPY_AND_ASSIGN(FieldValue);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100196 };
197
Fred Shih37f05ef2014-07-16 18:38:08 -0700198 void LogValue(FieldValueKind kind, MemberOffset offset, uint64_t value, bool is_volatile);
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800199 void UndoFieldWrite(mirror::Object* obj,
200 MemberOffset field_offset,
201 const FieldValue& field_value) const REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100202
203 // Maps field's offset to its value.
204 std::map<uint32_t, FieldValue> field_values_;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800205
206 DISALLOW_COPY_AND_ASSIGN(ObjectLog);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100207 };
208
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700209 class ArrayLog : public ValueObject {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100210 public:
211 void LogValue(size_t index, uint64_t value);
212
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800213 void Undo(mirror::Array* obj) const REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100214
215 size_t Size() const {
216 return array_values_.size();
217 }
218
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800219 ArrayLog() = default;
220 ArrayLog(ArrayLog&& log) = default;
221
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100222 private:
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800223 void UndoArrayWrite(mirror::Array* array,
224 Primitive::Type array_type,
225 size_t index,
226 uint64_t value) const REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100227
228 // Maps index to value.
229 // TODO use JValue instead ?
230 std::map<size_t, uint64_t> array_values_;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800231
232 DISALLOW_COPY_AND_ASSIGN(ArrayLog);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100233 };
234
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700235 class InternStringLog : public ValueObject {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100236 public:
237 enum StringKind {
238 kStrongString,
239 kWeakString
240 };
241 enum StringOp {
242 kInsert,
243 kRemove
244 };
Mathieu Chartier9e868092016-10-31 14:58:04 -0700245 InternStringLog(ObjPtr<mirror::String> s, StringKind kind, StringOp op);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100246
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800247 void Undo(InternTable* intern_table) const
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700248 REQUIRES_SHARED(Locks::mutator_lock_)
Mathieu Chartier90443472015-07-16 20:32:27 -0700249 REQUIRES(Locks::intern_table_lock_);
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700250 void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100251
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800252 InternStringLog() = default;
253 InternStringLog(InternStringLog&& log) = default;
254
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100255 private:
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800256 mutable GcRoot<mirror::String> str_;
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700257 const StringKind string_kind_;
258 const StringOp string_op_;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800259
260 DISALLOW_COPY_AND_ASSIGN(InternStringLog);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100261 };
262
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700263 class ResolveStringLog : public ValueObject {
264 public:
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800265 ResolveStringLog(ObjPtr<mirror::DexCache> dex_cache, dex::StringIndex string_idx);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700266
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800267 void Undo() const REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700268
269 void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
270
271 private:
272 GcRoot<mirror::DexCache> dex_cache_;
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800273 const dex::StringIndex string_idx_;
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800274
275 DISALLOW_COPY_AND_ASSIGN(ResolveStringLog);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700276 };
277
Mathieu Chartier38e954c2017-02-03 16:06:35 -0800278 void LogInternedString(InternStringLog&& log)
Mathieu Chartier90443472015-07-16 20:32:27 -0700279 REQUIRES(Locks::intern_table_lock_)
280 REQUIRES(!log_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100281
282 void UndoObjectModifications()
Mathieu Chartier90443472015-07-16 20:32:27 -0700283 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700284 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100285 void UndoArrayModifications()
Mathieu Chartier90443472015-07-16 20:32:27 -0700286 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700287 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100288 void UndoInternStringTableModifications()
Mathieu Chartier90443472015-07-16 20:32:27 -0700289 REQUIRES(Locks::intern_table_lock_)
290 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700291 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700292 void UndoResolveStringModifications()
293 REQUIRES(log_lock_)
294 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100295
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700296 void VisitObjectLogs(RootVisitor* visitor)
Mathieu Chartier90443472015-07-16 20:32:27 -0700297 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700298 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700299 void VisitArrayLogs(RootVisitor* visitor)
Mathieu Chartier90443472015-07-16 20:32:27 -0700300 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700301 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700302 void VisitInternStringLogs(RootVisitor* visitor)
303 REQUIRES(log_lock_)
304 REQUIRES_SHARED(Locks::mutator_lock_);
305 void VisitResolveStringLogs(RootVisitor* visitor)
Mathieu Chartier90443472015-07-16 20:32:27 -0700306 REQUIRES(log_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700307 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100308
Mathieu Chartier90443472015-07-16 20:32:27 -0700309 const std::string& GetAbortMessage() REQUIRES(!log_lock_);
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100310
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100311 Mutex log_lock_ ACQUIRED_AFTER(Locks::intern_table_lock_);
312 std::map<mirror::Object*, ObjectLog> object_logs_ GUARDED_BY(log_lock_);
313 std::map<mirror::Array*, ArrayLog> array_logs_ GUARDED_BY(log_lock_);
314 std::list<InternStringLog> intern_string_logs_ GUARDED_BY(log_lock_);
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700315 std::list<ResolveStringLog> resolve_string_logs_ GUARDED_BY(log_lock_);
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100316 bool aborted_ GUARDED_BY(log_lock_);
Chang Xing605fe242017-07-20 15:57:21 -0700317 bool rolling_back_; // Single thread, no race.
Vladimir Marko672c0802019-07-26 13:03:13 +0100318 gc::Heap* const heap_;
Vladimir Marko4d7b6892020-01-16 17:06:35 +0000319 const bool strict_;
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100320 std::string abort_message_ GUARDED_BY(log_lock_);
Chang Xingcade5c32017-07-20 17:56:26 -0700321 mirror::Class* root_ GUARDED_BY(log_lock_);
Vladimir Markob68bb7a2020-03-17 10:55:25 +0000322 const char* assert_no_new_records_reason_ GUARDED_BY(log_lock_);
323
324 friend class ScopedAssertNoNewTransactionRecords;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100325
326 DISALLOW_COPY_AND_ASSIGN(Transaction);
327};
328
Vladimir Markob68bb7a2020-03-17 10:55:25 +0000329class ScopedAssertNoNewTransactionRecords {
330 public:
331 explicit ScopedAssertNoNewTransactionRecords(const char* reason)
332 : transaction_(kIsDebugBuild ? InstallAssertion(reason) : nullptr) {}
333
334 ~ScopedAssertNoNewTransactionRecords() {
335 if (kIsDebugBuild && transaction_ != nullptr) {
336 RemoveAssertion(transaction_);
337 }
338 }
339
340 private:
341 static Transaction* InstallAssertion(const char* reason);
342 static void RemoveAssertion(Transaction* transaction);
343
344 Transaction* transaction_;
345};
346
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100347} // namespace art
348
349#endif // ART_RUNTIME_TRANSACTION_H_