// Copyright 2012 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef BASE_MEMORY_REF_COUNTED_MEMORY_H_ #define BASE_MEMORY_REF_COUNTED_MEMORY_H_ #include #include #include #include #include "base/base_export.h" #include "base/compiler_specific.h" #include "base/containers/span.h" #include "base/memory/raw_span.h" #include "base/memory/ref_counted.h" #include "base/memory/shared_memory_mapping.h" namespace base { class ReadOnlySharedMemoryRegion; // A generic interface to memory. This object is reference counted because most // of its subclasses own the data they carry, and this interface needs to // support heterogeneous containers of these different types of memory. // // The RefCountedMemory class provides a const view of the data it holds, as it // does not require all subclassing implementations to hold mutable data. If a // mutable view is required, the code must maintain awareness of the subclass // type, and can access it through there, such as: // - RefCountedBytes provides `as_vector()` to give mutable access to its data. // - RefCountedString provides `as_string()` to give mutable access to its data. class BASE_EXPORT RefCountedMemory : public RefCountedThreadSafe { public: // Returns true if `other` is byte for byte equal. bool Equals(const scoped_refptr& other) const; // Allow explicit conversion to `base::span`. Use a span to // access the data in a safe way, rather than calling `data()` explicitly. // // Example: // ``` // auto data = base::MakeRefCounted( // std::vector{1, 2, 3}); // base::span v = base::span(data); // v[2] = uint8_t{4}; // ``` const uint8_t* data() const LIFETIME_BOUND { return AsSpan().data(); } size_t size() const { return AsSpan().size(); } using iterator = base::span::iterator; iterator begin() const LIFETIME_BOUND { return AsSpan().begin(); } iterator end() const LIFETIME_BOUND { return AsSpan().end(); } // TODO(danakj): Remove all callers and remove this. const uint8_t* front() const LIFETIME_BOUND { return AsSpan().data(); } // The data/size members (or begin/end) give conversion to span already, but // we provide this operator as an optimization to combine two virtual method // calls into one. explicit operator base::span() const LIFETIME_BOUND { return AsSpan(); } protected: friend class RefCountedThreadSafe; RefCountedMemory(); virtual ~RefCountedMemory(); virtual base::span AsSpan() const LIFETIME_BOUND = 0; }; // An implementation of RefCountedMemory, for pointing to memory with a static // lifetime. Since the memory exists for the life of the program, the class can // not and does not need to take ownership of it. class BASE_EXPORT RefCountedStaticMemory : public RefCountedMemory { public: RefCountedStaticMemory(); explicit RefCountedStaticMemory(base::span bytes); RefCountedStaticMemory(const RefCountedStaticMemory&) = delete; RefCountedStaticMemory& operator=(const RefCountedStaticMemory&) = delete; private: ~RefCountedStaticMemory() override; // RefCountedMemory: base::span AsSpan() const LIFETIME_BOUND override; base::raw_span bytes_; }; // An implementation of RefCountedMemory, where the data is stored in a STL // vector. class BASE_EXPORT RefCountedBytes : public RefCountedMemory { public: RefCountedBytes(); // Constructs a RefCountedBytes object by taking `initializer`. explicit RefCountedBytes(std::vector initializer); // Constructs a RefCountedBytes object by copying from `initializer`. explicit RefCountedBytes(base::span initializer); // Constructs a RefCountedBytes object by zero-initializing a new vector of // `size` bytes. explicit RefCountedBytes(size_t size); RefCountedBytes(const RefCountedBytes&) = delete; RefCountedBytes& operator=(const RefCountedBytes&) = delete; const std::vector& as_vector() const { return bytes_; } std::vector& as_vector() { return bytes_; } private: ~RefCountedBytes() override; // RefCountedMemory: base::span AsSpan() const LIFETIME_BOUND override; std::vector bytes_; }; // An implementation of RefCountedMemory, where the bytes are stored in a STL // string. Use this if your data naturally arrives in that format. class BASE_EXPORT RefCountedString : public RefCountedMemory { public: RefCountedString(); explicit RefCountedString(std::string value); RefCountedString(const RefCountedString&) = delete; RefCountedString& operator=(const RefCountedString&) = delete; const std::string& as_string() const LIFETIME_BOUND { return string_; } std::string& as_string() LIFETIME_BOUND { return string_; } private: ~RefCountedString() override; // RefCountedMemory: base::span AsSpan() const LIFETIME_BOUND override; std::string string_; }; // An implementation of RefCountedMemory, where the bytes are stored in a // std::u16string. class BASE_EXPORT RefCountedString16 : public base::RefCountedMemory { public: RefCountedString16(); explicit RefCountedString16(std::u16string value); RefCountedString16(const RefCountedString16&) = delete; RefCountedString16& operator=(const RefCountedString16&) = delete; const std::u16string& as_string() const LIFETIME_BOUND { return string_; } std::u16string& as_string() LIFETIME_BOUND { return string_; } private: ~RefCountedString16() override; // RefCountedMemory: base::span AsSpan() const LIFETIME_BOUND override; std::u16string string_; }; // An implementation of RefCountedMemory, where the bytes are stored in // ReadOnlySharedMemoryMapping. class BASE_EXPORT RefCountedSharedMemoryMapping : public RefCountedMemory { public: // Constructs a RefCountedMemory object by taking ownership of an already // mapped ReadOnlySharedMemoryMapping object. explicit RefCountedSharedMemoryMapping(ReadOnlySharedMemoryMapping mapping); RefCountedSharedMemoryMapping(const RefCountedSharedMemoryMapping&) = delete; RefCountedSharedMemoryMapping& operator=( const RefCountedSharedMemoryMapping&) = delete; // Convenience method to map all of `region` and take ownership of the // mapping. Returns a null `scoped_refptr` if the map operation fails. static scoped_refptr CreateFromWholeRegion( const ReadOnlySharedMemoryRegion& region); private: ~RefCountedSharedMemoryMapping() override; // RefCountedMemory: base::span AsSpan() const LIFETIME_BOUND override; const ReadOnlySharedMemoryMapping mapping_; }; } // namespace base #endif // BASE_MEMORY_REF_COUNTED_MEMORY_H_