Chromium Code Reviews| Index: base/metrics/persistent_memory_allocator.h |
| diff --git a/base/metrics/persistent_memory_allocator.h b/base/metrics/persistent_memory_allocator.h |
| index 94a7744bfb2714d74ae956b41e1ceff7483176e2..d52b6e9b32fbf6e4407852b7d0e4880dbe070c52 100644 |
| --- a/base/metrics/persistent_memory_allocator.h |
| +++ b/base/metrics/persistent_memory_allocator.h |
| @@ -767,6 +767,96 @@ class BASE_EXPORT FilePersistentMemoryAllocator |
| }; |
| #endif // !defined(OS_NACL) |
| +// An allocation that is defined but not executed until required at a later |
| +// time. This allows for potential users of an allocation to be decoupled |
| +// from the logic that defines it. In addition, there can be multiple users |
| +// of the same allocation or any region thereof that are guaranteed to always |
| +// use the same space. It's okay to copy/move these objects. |
| +// |
| +// This is a top-level class instead of an inner class of the PMA so that it |
| +// can be forward-declared in other header files without the need to include |
| +// the full contents of this file. |
| +class BASE_EXPORT DelayedPersistentAllocation { |
| + public: |
| + using Reference = PersistentMemoryAllocator::Reference; |
| + |
| + // Creates a delayed allocation using the specified |allocator|. When |
| + // needed, the memory will be allocated using the specified |type| and |
| + // |size|. If |offset| is given, the returned pointer will be at that |
|
Alexei Svitkine (slow)
2017/04/12 17:04:25
Please expand comment to make explicit whether |si
bcwhite
2017/04/12 21:23:43
Done.
|
| + // offset into the segment; this allows combining allocations into a |
| + // single persistent segment to reduce overhead and means as "all or |
|
Alexei Svitkine (slow)
2017/04/12 17:04:25
Nit: "means as" -> "means an"
bcwhite
2017/04/12 21:23:42
Done.
|
| + // nothing" request. |
| + // |
| + // Once allocated, a reference to the segment will be stored at |ref|. |
| + // This shared location must be initialized to zero (0); it is checked |
| + // with every Get() request to see if the allocation has already been |
| + // done. |
| + // |
| + // For conveience, methods taking both Atomic32 and std::atomic<Reference> |
|
Alexei Svitkine (slow)
2017/04/12 17:04:25
Nit: convenience
bcwhite
2017/04/12 21:23:42
Done.
|
| + // are defined. |
| + DelayedPersistentAllocation(PersistentMemoryAllocator* allocator, |
| + subtle::Atomic32* ref, |
| + uint32_t type, |
| + size_t size); |
| + DelayedPersistentAllocation(PersistentMemoryAllocator* allocator, |
| + subtle::Atomic32* ref, |
| + uint32_t type, |
| + size_t size, |
| + size_t offset); |
| + DelayedPersistentAllocation(PersistentMemoryAllocator* allocator, |
| + std::atomic<Reference>* ref, |
| + uint32_t type, |
| + size_t size); |
| + DelayedPersistentAllocation(PersistentMemoryAllocator* allocator, |
| + std::atomic<Reference>* ref, |
| + uint32_t type, |
| + size_t size, |
| + size_t offset); |
| + ~DelayedPersistentAllocation(); |
| + |
| + // Make this allocation "iterable" when realized. |
| + void MakeIterable(); |
| + |
| + // Gets a pointer to the defined allocation. This will realize the request |
| + // and update the reference provided during construction. The memory will |
| + // be zeroed the first time it is returned, after that it is shared with |
| + // all other Get() requests and so shows any changes made to it elsewhere. |
| + // |
| + // If the allocation fails for any reason, null will be returned. This works |
| + // even on "const" objects because the allocation is already defined, just |
| + // delayed. |
| + void* Get() const; |
| + |
| + // Gets the internal reference value. If this returns a non-zero value then |
| + // a subsequent call to Get() will do nothing but convert that reference into |
| + // a memory location -- useful for accessing an existing allocation without |
| + // creating one unnecessarily. |
| + Reference reference() const { |
| + return reference_->load(std::memory_order_relaxed); |
| + } |
| + |
| + private: |
| + // The underlying object that does the actual allocation of memory. Its |
| + // lifetime must exceed that of all DelayedPersistentAllocation objects |
| + // that use it. |
| + PersistentMemoryAllocator* const allocator_; |
| + |
| + // The desired type and size of the allocated segment plus the offset |
| + // within it for the defined request. |
| + uint32_t const type_; |
|
Alexei Svitkine (slow)
2017/04/12 17:04:25
Nit: I think for primitive types, it's more common
bcwhite
2017/04/12 21:23:42
Done.
|
| + size_t const size_; |
| + size_t const offset_; |
| + |
| + // The location at which a reference to the allocated segment is to be |
| + // stored once the allocation is complete. If multiple delayed allocations |
| + // share the same pointer then an allocation on one will amount to an |
| + // allocation for all. |
| + volatile std::atomic<Reference>* const reference_; |
| + |
| + // Flag indicating if allocation should be made iterable when done. |
| + bool make_iterable_ = false; |
| +}; |
|
Alexei Svitkine (slow)
2017/04/12 17:04:25
DISALLOW_COPY_AND_ASSIGN()?
bcwhite
2017/04/12 21:23:42
No, it's explicitly allowed and safe. This makes
Alexei Svitkine (slow)
2017/04/21 15:14:16
Okay, add a comment about it then in the same plac
bcwhite
2017/04/21 15:59:04
Done.
|
| + |
| } // namespace base |
| #endif // BASE_METRICS_PERSISTENT_MEMORY_ALLOCATOR_H_ |