Chromium Code Reviews| Index: base/metrics/persistent_memory_allocator.cc |
| diff --git a/base/metrics/persistent_memory_allocator.cc b/base/metrics/persistent_memory_allocator.cc |
| index d381d8784d1094e1d883db24a6ce03eee6300e27..4f372b8ca113a5642bafed23959ac6ab594f420a 100644 |
| --- a/base/metrics/persistent_memory_allocator.cc |
| +++ b/base/metrics/persistent_memory_allocator.cc |
| @@ -1063,4 +1063,95 @@ void FilePersistentMemoryAllocator::FlushPartial(size_t length, bool sync) { |
| } |
| #endif // !defined(OS_NACL) |
| +//----- DelayedPersistentAllocation -------------------------------------------- |
| + |
| +// Forwarding constructors. |
| +DelayedPersistentAllocation::DelayedPersistentAllocation( |
| + PersistentMemoryAllocator* allocator, |
| + subtle::Atomic32* ref, |
| + uint32_t type, |
| + size_t size) |
| + : DelayedPersistentAllocation( |
| + allocator, |
| + reinterpret_cast<std::atomic<Reference>*>(ref), |
| + type, |
| + size, |
| + 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.
|
| +DelayedPersistentAllocation::DelayedPersistentAllocation( |
| + PersistentMemoryAllocator* allocator, |
| + subtle::Atomic32* ref, |
| + uint32_t type, |
| + size_t size, |
| + size_t offset) |
| + : DelayedPersistentAllocation( |
| + allocator, |
| + reinterpret_cast<std::atomic<Reference>*>(ref), |
| + type, |
| + size, |
| + offset) {} |
| +DelayedPersistentAllocation::DelayedPersistentAllocation( |
| + PersistentMemoryAllocator* allocator, |
| + std::atomic<Reference>* ref, |
| + uint32_t type, |
| + size_t size) |
| + : DelayedPersistentAllocation(allocator, ref, type, size, 0) {} |
| + |
| +// Real constructor. |
| +DelayedPersistentAllocation::DelayedPersistentAllocation( |
| + PersistentMemoryAllocator* allocator, |
| + std::atomic<Reference>* ref, |
| + uint32_t type, |
| + size_t size, |
| + size_t offset) |
| + : allocator_(allocator), |
| + type_(type), |
| + size_(size), |
| + offset_(offset), |
| + 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.
|
| + |
| +DelayedPersistentAllocation::~DelayedPersistentAllocation() {} |
| + |
| +void DelayedPersistentAllocation::MakeIterable() { |
| + 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
|
| +} |
| + |
| +void* DelayedPersistentAllocation::Get() const { |
| + // 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.
|
| + // contents of the allocation in any way. |
| + Reference ref = reference_->load(std::memory_order_relaxed); |
| + if (!ref) { |
| + ref = allocator_->Allocate(size_, type_); |
| + if (!ref) |
| + return nullptr; |
| + |
| + // Store the new reference in its proper location using compare-and-swap. |
| + // Use a "strong" exchange to ensure no false-negatives since the operation |
| + // cannot be retried. |
| + Reference existing = 0; // Must be mutable; receives actual value. |
| + if (reference_->compare_exchange_strong(existing, ref, |
| + std::memory_order_relaxed, |
| + std::memory_order_relaxed)) { |
| + if (make_iterable_) |
| + allocator_->MakeIterable(ref); |
| + } else { |
| + // Failure indicates that something else has raced ahead, performed the |
| + // 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.
|
| + // and use the other one instead. |
| + DCHECK_EQ(type_, allocator_->GetType(existing)); |
| + DCHECK_LE(size_, allocator_->GetAllocSize(existing)); |
| + allocator_->ChangeType(ref, 0, type_, /*clear=*/false); |
| + ref = existing; |
| + } |
| + } |
| + |
| + char* mem = allocator_->GetAsArray<char>(ref, type_, size_); |
| + if (!mem) { |
| + // This should never happen but be tolerant if it does as corruption from |
| + // the outside is something to guard against. |
| + NOTREACHED(); |
| + return nullptr; |
| + } |
| + return mem + offset_; |
| +} |
| + |
| } // namespace base |