| 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..b931b2f6b61add814a5a1ad3c4436fd3280758d1 100644
|
| --- a/base/metrics/persistent_memory_allocator.h
|
| +++ b/base/metrics/persistent_memory_allocator.h
|
| @@ -767,6 +767,102 @@ 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
|
| + // offset into the segment; this allows combining allocations into a
|
| + // single persistent segment to reduce overhead and means an "all or
|
| + // nothing" request. Note that |size| is always the total memory size
|
| + // and |offset| is just indicating the start of a block within it. If
|
| + // |make_iterable| was true, the allocation will made iterable when it
|
| + // is created; already existing allocations are not changed.
|
| + //
|
| + // 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 convenience, methods taking both Atomic32 and std::atomic<Reference>
|
| + // are defined.
|
| + DelayedPersistentAllocation(PersistentMemoryAllocator* allocator,
|
| + subtle::Atomic32* ref,
|
| + uint32_t type,
|
| + size_t size,
|
| + bool make_iterable);
|
| + DelayedPersistentAllocation(PersistentMemoryAllocator* allocator,
|
| + subtle::Atomic32* ref,
|
| + uint32_t type,
|
| + size_t size,
|
| + size_t offset,
|
| + bool make_iterable);
|
| + DelayedPersistentAllocation(PersistentMemoryAllocator* allocator,
|
| + std::atomic<Reference>* ref,
|
| + uint32_t type,
|
| + size_t size,
|
| + bool make_iterable);
|
| + DelayedPersistentAllocation(PersistentMemoryAllocator* allocator,
|
| + std::atomic<Reference>* ref,
|
| + uint32_t type,
|
| + size_t size,
|
| + size_t offset,
|
| + bool make_iterable);
|
| + ~DelayedPersistentAllocation();
|
| +
|
| + // 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.
|
| + const uint32_t type_;
|
| + const size_t size_;
|
| + const size_t offset_;
|
| +
|
| + // Flag indicating if allocation should be made iterable when done.
|
| + const bool make_iterable_;
|
| +
|
| + // 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_;
|
| +
|
| + // No DISALLOW_COPY_AND_ASSIGN as it's okay to copy/move these objects.
|
| +};
|
| +
|
| } // namespace base
|
|
|
| #endif // BASE_METRICS_PERSISTENT_MEMORY_ALLOCATOR_H_
|
|
|