1 // Copyright 2021 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_MEMORY_UNSAFE_SHARED_MEMORY_POOL_H_ 6 #define BASE_MEMORY_UNSAFE_SHARED_MEMORY_POOL_H_ 7 8 #include <memory> 9 #include <utility> 10 #include <vector> 11 12 #include "base/base_export.h" 13 #include "base/memory/ref_counted.h" 14 #include "base/memory/unsafe_shared_memory_region.h" 15 #include "base/synchronization/lock.h" 16 #include "base/types/pass_key.h" 17 18 namespace base { 19 20 // UnsafeSharedMemoryPool manages allocation and pooling of 21 // UnsafeSharedMemoryRegions. Using pool saves cost of repeated shared memory 22 // allocations. Up-to 32 regions would be pooled. It is thread-safe. May return 23 // bigger regions than requested. If a requested size is increased, all stored 24 // regions are purged. Regions are returned to the buffer on destruction of 25 // |SharedMemoryHandle| if they are of a correct size. 26 class BASE_EXPORT UnsafeSharedMemoryPool 27 : public RefCountedThreadSafe<UnsafeSharedMemoryPool> { 28 public: 29 // Used to store the allocation result. 30 // This class returns memory to the pool upon destruction. 31 class BASE_EXPORT Handle { 32 public: 33 Handle(PassKey<UnsafeSharedMemoryPool>, 34 UnsafeSharedMemoryRegion region, 35 WritableSharedMemoryMapping mapping, 36 scoped_refptr<UnsafeSharedMemoryPool> pool); 37 38 ~Handle(); 39 // Disallow copy and assign. 40 Handle(const Handle&) = delete; 41 Handle& operator=(const Handle&) = delete; 42 43 const UnsafeSharedMemoryRegion& GetRegion() const; 44 45 const WritableSharedMemoryMapping& GetMapping() const; 46 47 private: 48 UnsafeSharedMemoryRegion region_; 49 WritableSharedMemoryMapping mapping_; 50 scoped_refptr<UnsafeSharedMemoryPool> pool_; 51 }; 52 53 UnsafeSharedMemoryPool(); 54 // Disallow copy and assign. 55 UnsafeSharedMemoryPool(const UnsafeSharedMemoryPool&) = delete; 56 UnsafeSharedMemoryPool& operator=(const UnsafeSharedMemoryPool&) = delete; 57 58 // Allocates a region of the given |size| or reuses a previous allocation if 59 // possible. 60 std::unique_ptr<Handle> MaybeAllocateBuffer(size_t size); 61 62 // Shuts down the pool, freeing all currently unused allocations and freeing 63 // outstanding ones as they are returned. 64 void Shutdown(); 65 66 private: 67 friend class RefCountedThreadSafe<UnsafeSharedMemoryPool>; 68 ~UnsafeSharedMemoryPool(); 69 70 void ReleaseBuffer(UnsafeSharedMemoryRegion region, 71 WritableSharedMemoryMapping mapping); 72 73 Lock lock_; 74 // All shared memory regions cached internally are guaranteed to be 75 // at least `region_size_` bytes in size. 76 size_t region_size_ GUARDED_BY(lock_) = 0u; 77 // Cached unused regions and their mappings. 78 std::vector<std::pair<UnsafeSharedMemoryRegion, WritableSharedMemoryMapping>> 79 regions_ GUARDED_BY(lock_); 80 bool is_shutdown_ GUARDED_BY(lock_) = false; 81 }; 82 83 } // namespace base 84 85 #endif // BASE_MEMORY_UNSAFE_SHARED_MEMORY_POOL_H_ 86