| // Copyright 2018 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef BASE_MEMORY_SHARED_MEMORY_MAPPING_H_ |
| #define BASE_MEMORY_SHARED_MEMORY_MAPPING_H_ |
| |
| #if !defined(STARBOARD) |
| |
| #include <cstddef> |
| |
| #include "base/containers/span.h" |
| #include "base/macros.h" |
| #include "base/unguessable_token.h" |
| |
| namespace base { |
| |
| namespace subtle { |
| class PlatformSharedMemoryRegion; |
| } // namespace subtle |
| |
| // Base class for scoped handles to a shared memory mapping created from a |
| // shared memory region. Created shared memory mappings remain valid even if the |
| // creator region is transferred or destroyed. |
| // |
| // Each mapping has an UnguessableToken that identifies the shared memory region |
| // it was created from. This is used for memory metrics, to avoid overcounting |
| // shared memory. |
| class BASE_EXPORT SharedMemoryMapping { |
| public: |
| // Default constructor initializes an invalid instance. |
| SharedMemoryMapping(); |
| |
| // Move operations are allowed. |
| SharedMemoryMapping(SharedMemoryMapping&& mapping); |
| SharedMemoryMapping& operator=(SharedMemoryMapping&& mapping); |
| |
| // Unmaps the region if the mapping is valid. |
| virtual ~SharedMemoryMapping(); |
| |
| // Returns true iff the mapping is valid. False means there is no |
| // corresponding area of memory. |
| bool IsValid() const { return memory_ != nullptr; } |
| |
| // Returns the logical size of the mapping in bytes. This is precisely the |
| // size requested by whoever created the mapping, and it is always less than |
| // or equal to |mapped_size()|. This is undefined for invalid instances. |
| size_t size() const { |
| DCHECK(IsValid()); |
| return size_; |
| } |
| |
| // Returns the actual size of the mapping in bytes. This is always at least |
| // as large as |size()| but may be larger due to platform mapping alignment |
| // constraints. This is undefined for invalid instances. |
| size_t mapped_size() const { |
| DCHECK(IsValid()); |
| return mapped_size_; |
| } |
| |
| // Returns 128-bit GUID of the region this mapping belongs to. |
| const UnguessableToken& guid() const { |
| DCHECK(IsValid()); |
| return guid_; |
| } |
| |
| protected: |
| SharedMemoryMapping(void* address, |
| size_t size, |
| size_t mapped_size, |
| const UnguessableToken& guid); |
| void* raw_memory_ptr() const { return memory_; } |
| |
| private: |
| friend class SharedMemoryTracker; |
| |
| void Unmap(); |
| |
| void* memory_ = nullptr; |
| size_t size_ = 0; |
| size_t mapped_size_ = 0; |
| UnguessableToken guid_; |
| |
| DISALLOW_COPY_AND_ASSIGN(SharedMemoryMapping); |
| }; |
| |
| // Class modeling a read-only mapping of a shared memory region into the |
| // current process' address space. This is created by ReadOnlySharedMemoryRegion |
| // instances. |
| class BASE_EXPORT ReadOnlySharedMemoryMapping : public SharedMemoryMapping { |
| public: |
| // Default constructor initializes an invalid instance. |
| ReadOnlySharedMemoryMapping(); |
| |
| // Move operations are allowed. |
| ReadOnlySharedMemoryMapping(ReadOnlySharedMemoryMapping&&); |
| ReadOnlySharedMemoryMapping& operator=(ReadOnlySharedMemoryMapping&&); |
| |
| // Returns the base address of the mapping. This is read-only memory. This is |
| // page-aligned. This is nullptr for invalid instances. |
| const void* memory() const { return raw_memory_ptr(); } |
| |
| // Returns a pointer to a page-aligned const T if the mapping is valid and |
| // large enough to contain a T, or nullptr otherwise. |
| template <typename T> |
| const T* GetMemoryAs() const { |
| if (!IsValid()) |
| return nullptr; |
| if (sizeof(T) > size()) |
| return nullptr; |
| return static_cast<const T*>(raw_memory_ptr()); |
| } |
| |
| // Returns a span of const T. The number of elements is autodeduced from the |
| // size of the shared memory mapping. The number of elements may be |
| // autodeduced as zero, i.e. the mapping is invalid or the size of the mapping |
| // isn't large enough to contain even one T: in that case, an empty span |
| // will be returned. The first element, if any, is guaranteed to be |
| // page-aligned. |
| template <typename T> |
| span<const T> GetMemoryAsSpan() const { |
| if (!IsValid()) |
| return span<const T>(); |
| size_t count = size() / sizeof(T); |
| return GetMemoryAsSpan<T>(count); |
| } |
| |
| // Returns a span of const T with |count| elements if the mapping is valid and |
| // large enough to contain |count| elements, or an empty span otherwise. The |
| // first element, if any, is guaranteed to be page-aligned. |
| template <typename T> |
| span<const T> GetMemoryAsSpan(size_t count) const { |
| if (!IsValid()) |
| return span<const T>(); |
| if (size() / sizeof(T) < count) |
| return span<const T>(); |
| return span<const T>(static_cast<const T*>(raw_memory_ptr()), count); |
| } |
| |
| private: |
| friend class ReadOnlySharedMemoryRegion; |
| ReadOnlySharedMemoryMapping(void* address, |
| size_t size, |
| size_t mapped_size, |
| const UnguessableToken& guid); |
| |
| DISALLOW_COPY_AND_ASSIGN(ReadOnlySharedMemoryMapping); |
| }; |
| |
| // Class modeling a writable mapping of a shared memory region into the |
| // current process' address space. This is created by *SharedMemoryRegion |
| // instances. |
| class BASE_EXPORT WritableSharedMemoryMapping : public SharedMemoryMapping { |
| public: |
| // Default constructor initializes an invalid instance. |
| WritableSharedMemoryMapping(); |
| |
| // Move operations are allowed. |
| WritableSharedMemoryMapping(WritableSharedMemoryMapping&&); |
| WritableSharedMemoryMapping& operator=(WritableSharedMemoryMapping&&); |
| |
| // Returns the base address of the mapping. This is writable memory. This is |
| // page-aligned. This is nullptr for invalid instances. |
| void* memory() const { return raw_memory_ptr(); } |
| |
| // Returns a pointer to a page-aligned T if the mapping is valid and large |
| // enough to contain a T, or nullptr otherwise. |
| template <typename T> |
| T* GetMemoryAs() const { |
| if (!IsValid()) |
| return nullptr; |
| if (sizeof(T) > size()) |
| return nullptr; |
| return static_cast<T*>(raw_memory_ptr()); |
| } |
| |
| // Returns a span of T. The number of elements is autodeduced from the size of |
| // the shared memory mapping. The number of elements may be autodeduced as |
| // zero, i.e. the mapping is invalid or the size of the mapping isn't large |
| // enough to contain even one T: in that case, an empty span will be returned. |
| // The first element, if any, is guaranteed to be page-aligned. |
| template <typename T> |
| span<T> GetMemoryAsSpan() const { |
| if (!IsValid()) |
| return span<T>(); |
| size_t count = size() / sizeof(T); |
| return GetMemoryAsSpan<T>(count); |
| } |
| |
| // Returns a span of T with |count| elements if the mapping is valid and large |
| // enough to contain |count| elements, or an empty span otherwise. The first |
| // element, if any, is guaranteed to be page-aligned. |
| template <typename T> |
| span<T> GetMemoryAsSpan(size_t count) const { |
| if (!IsValid()) |
| return span<T>(); |
| if (size() / sizeof(T) < count) |
| return span<T>(); |
| return span<T>(static_cast<T*>(raw_memory_ptr()), count); |
| } |
| |
| private: |
| friend WritableSharedMemoryMapping MapAtForTesting( |
| subtle::PlatformSharedMemoryRegion* region, |
| off_t offset, |
| size_t size); |
| friend class ReadOnlySharedMemoryRegion; |
| friend class WritableSharedMemoryRegion; |
| friend class UnsafeSharedMemoryRegion; |
| WritableSharedMemoryMapping(void* address, |
| size_t size, |
| size_t mapped_size, |
| const UnguessableToken& guid); |
| |
| DISALLOW_COPY_AND_ASSIGN(WritableSharedMemoryMapping); |
| }; |
| |
| } // namespace base |
| |
| #endif // !defined(STARBOARD) |
| #endif // BASE_MEMORY_SHARED_MEMORY_MAPPING_H_ |