OLD | NEW |
---|---|
1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/metrics/persistent_memory_allocator.h" | 5 #include "base/metrics/persistent_memory_allocator.h" |
6 | 6 |
7 #include <assert.h> | 7 #include <assert.h> |
8 #include <algorithm> | 8 #include <algorithm> |
9 | 9 |
10 #if defined(OS_WIN) | 10 #if defined(OS_WIN) |
(...skipping 1045 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1056 // been written to disk and so is applicable to "flush". | 1056 // been written to disk and so is applicable to "flush". |
1057 int result = ::msync(const_cast<void*>(data()), length, | 1057 int result = ::msync(const_cast<void*>(data()), length, |
1058 MS_INVALIDATE | (sync ? MS_SYNC : MS_ASYNC)); | 1058 MS_INVALIDATE | (sync ? MS_SYNC : MS_ASYNC)); |
1059 DCHECK_NE(EINVAL, result); | 1059 DCHECK_NE(EINVAL, result); |
1060 #else | 1060 #else |
1061 #error Unsupported OS. | 1061 #error Unsupported OS. |
1062 #endif | 1062 #endif |
1063 } | 1063 } |
1064 #endif // !defined(OS_NACL) | 1064 #endif // !defined(OS_NACL) |
1065 | 1065 |
1066 //----- DelayedPersistentAllocation -------------------------------------------- | |
1067 | |
1068 // Forwarding constructors. | |
1069 DelayedPersistentAllocation::DelayedPersistentAllocation( | |
1070 PersistentMemoryAllocator* allocator, | |
1071 subtle::Atomic32* ref, | |
1072 uint32_t type, | |
1073 size_t size) | |
1074 : DelayedPersistentAllocation( | |
1075 allocator, | |
1076 reinterpret_cast<std::atomic<Reference>*>(ref), | |
1077 type, | |
1078 size, | |
1079 0) {} | |
Alexei Svitkine (slow)
2017/04/12 17:04:24
Nit: Add empty lines between ctors to make it easi
bcwhite
2017/04/12 21:23:42
Done.
| |
1080 DelayedPersistentAllocation::DelayedPersistentAllocation( | |
1081 PersistentMemoryAllocator* allocator, | |
1082 subtle::Atomic32* ref, | |
1083 uint32_t type, | |
1084 size_t size, | |
1085 size_t offset) | |
1086 : DelayedPersistentAllocation( | |
1087 allocator, | |
1088 reinterpret_cast<std::atomic<Reference>*>(ref), | |
1089 type, | |
1090 size, | |
1091 offset) {} | |
1092 DelayedPersistentAllocation::DelayedPersistentAllocation( | |
1093 PersistentMemoryAllocator* allocator, | |
1094 std::atomic<Reference>* ref, | |
1095 uint32_t type, | |
1096 size_t size) | |
1097 : DelayedPersistentAllocation(allocator, ref, type, size, 0) {} | |
1098 | |
1099 // Real constructor. | |
1100 DelayedPersistentAllocation::DelayedPersistentAllocation( | |
1101 PersistentMemoryAllocator* allocator, | |
1102 std::atomic<Reference>* ref, | |
1103 uint32_t type, | |
1104 size_t size, | |
1105 size_t offset) | |
1106 : allocator_(allocator), | |
1107 type_(type), | |
1108 size_(size), | |
1109 offset_(offset), | |
1110 reference_(ref) {} | |
Alexei Svitkine (slow)
2017/04/12 17:04:25
Nit: Add a DCHECK() on the ref ptr not being null?
bcwhite
2017/04/12 21:23:42
Done.
| |
1111 | |
1112 DelayedPersistentAllocation::~DelayedPersistentAllocation() {} | |
1113 | |
1114 void DelayedPersistentAllocation::MakeIterable() { | |
1115 make_iterable_ = true; | |
Alexei Svitkine (slow)
2017/04/12 17:04:24
How about the case where it was created already an
bcwhite
2017/04/12 21:23:42
It would be called when the object is created and
Alexei Svitkine (slow)
2017/04/21 15:14:16
Let's make it a ctor param them - to avoid confusi
bcwhite
2017/04/21 15:59:04
I like it better as a ctor parameter. Less confus
| |
1116 } | |
1117 | |
1118 void* DelayedPersistentAllocation::Get() const { | |
1119 // Relaxed operations is acceptable here because it's not protecting the | |
Alexei Svitkine (slow)
2017/04/12 17:04:25
Nit: is -> are
bcwhite
2017/04/12 21:23:42
Done.
| |
1120 // contents of the allocation in any way. | |
1121 Reference ref = reference_->load(std::memory_order_relaxed); | |
1122 if (!ref) { | |
1123 ref = allocator_->Allocate(size_, type_); | |
1124 if (!ref) | |
1125 return nullptr; | |
1126 | |
1127 // Store the new reference in its proper location using compare-and-swap. | |
1128 // Use a "strong" exchange to ensure no false-negatives since the operation | |
1129 // cannot be retried. | |
1130 Reference existing = 0; // Must be mutable; receives actual value. | |
1131 if (reference_->compare_exchange_strong(existing, ref, | |
1132 std::memory_order_relaxed, | |
1133 std::memory_order_relaxed)) { | |
1134 if (make_iterable_) | |
1135 allocator_->MakeIterable(ref); | |
1136 } else { | |
1137 // Failure indicates that something else has raced ahead, performed the | |
1138 // allocation, and stored its reference. Purge the allocation just done | |
Alexei Svitkine (slow)
2017/04/12 17:04:25
Nit: "that was just done" as otherwise it's a bit
bcwhite
2017/04/12 21:23:42
Done.
| |
1139 // and use the other one instead. | |
1140 DCHECK_EQ(type_, allocator_->GetType(existing)); | |
1141 DCHECK_LE(size_, allocator_->GetAllocSize(existing)); | |
1142 allocator_->ChangeType(ref, 0, type_, /*clear=*/false); | |
1143 ref = existing; | |
1144 } | |
1145 } | |
1146 | |
1147 char* mem = allocator_->GetAsArray<char>(ref, type_, size_); | |
1148 if (!mem) { | |
1149 // This should never happen but be tolerant if it does as corruption from | |
1150 // the outside is something to guard against. | |
1151 NOTREACHED(); | |
1152 return nullptr; | |
1153 } | |
1154 return mem + offset_; | |
1155 } | |
1156 | |
1066 } // namespace base | 1157 } // namespace base |
OLD | NEW |