Implement base::RefCountedSharedMemory.
This base::RefCountedMemory subclass owns a base::SharedMemory instance.
Use this class to easily access data in shared memory via the
base::RefCountedMemory interface without having to copy it out to a
std::string or std::vector.
Use this in printing code to avoid a bunch of copying.
Change-Id: I275eacb3af0250d352ec909429d8563b28b1b57e
Reviewed-on: https://chromium-review.googlesource.com/978641
Commit-Queue: Lei Zhang <[email protected]>
Reviewed-by: Wei Li <[email protected]>
Reviewed-by: Rebekah Potter <[email protected]>
Reviewed-by: Reilly Grant <[email protected]>
Cr-Commit-Position: refs/heads/master@{#547048}
diff --git a/base/memory/ref_counted_memory.cc b/base/memory/ref_counted_memory.cc
index be981e32..7999d90 100644
--- a/base/memory/ref_counted_memory.cc
+++ b/base/memory/ref_counted_memory.cc
@@ -4,6 +4,8 @@
#include "base/memory/ref_counted_memory.h"
+#include <utility>
+
#include "base/logging.h"
namespace base {
@@ -80,4 +82,24 @@
return data_.size();
}
+RefCountedSharedMemory::RefCountedSharedMemory(
+ std::unique_ptr<SharedMemory> shm,
+ size_t size)
+ : shm_(std::move(shm)), size_(size) {
+ DCHECK(shm_);
+ DCHECK(shm_->memory());
+ DCHECK_GT(size_, 0U);
+ DCHECK_LE(size_, shm_->mapped_size());
+}
+
+RefCountedSharedMemory::~RefCountedSharedMemory() = default;
+
+const unsigned char* RefCountedSharedMemory::front() const {
+ return reinterpret_cast<const unsigned char*>(shm_->memory());
+}
+
+size_t RefCountedSharedMemory::size() const {
+ return size_;
+}
+
} // namespace base
diff --git a/base/memory/ref_counted_memory.h b/base/memory/ref_counted_memory.h
index 9d29922..82a3eeb1 100644
--- a/base/memory/ref_counted_memory.h
+++ b/base/memory/ref_counted_memory.h
@@ -7,12 +7,14 @@
#include <stddef.h>
+#include <memory>
#include <string>
#include <vector>
#include "base/base_export.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/shared_memory.h"
namespace base {
@@ -136,6 +138,27 @@
DISALLOW_COPY_AND_ASSIGN(RefCountedString);
};
+// An implementation of RefCountedMemory, where the bytes are stored in shared
+// memory.
+class BASE_EXPORT RefCountedSharedMemory : public RefCountedMemory {
+ public:
+ // Constructs a RefCountedMemory object by taking ownership of an already
+ // mapped SharedMemory object.
+ RefCountedSharedMemory(std::unique_ptr<SharedMemory> shm, size_t size);
+
+ // RefCountedMemory:
+ const unsigned char* front() const override;
+ size_t size() const override;
+
+ private:
+ ~RefCountedSharedMemory() override;
+
+ const std::unique_ptr<SharedMemory> shm_;
+ const size_t size_;
+
+ DISALLOW_COPY_AND_ASSIGN(RefCountedSharedMemory);
+};
+
} // namespace base
#endif // BASE_MEMORY_REF_COUNTED_MEMORY_H_
diff --git a/base/memory/ref_counted_memory_unittest.cc b/base/memory/ref_counted_memory_unittest.cc
index 72046e52..43f7bbe 100644
--- a/base/memory/ref_counted_memory_unittest.cc
+++ b/base/memory/ref_counted_memory_unittest.cc
@@ -6,6 +6,8 @@
#include <stdint.h>
+#include <utility>
+
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -70,6 +72,20 @@
EXPECT_EQ('e', mem->front()[9]);
}
+TEST(RefCountedMemoryUnitTest, RefCountedSharedMemory) {
+ static const char kData[] = "shm_dummy_data";
+ auto shm = std::make_unique<SharedMemory>();
+ ASSERT_TRUE(shm->CreateAndMapAnonymous(sizeof(kData)));
+ memcpy(shm->memory(), kData, sizeof(kData));
+
+ auto mem =
+ MakeRefCounted<RefCountedSharedMemory>(std::move(shm), sizeof(kData));
+ ASSERT_EQ(sizeof(kData), mem->size());
+ EXPECT_EQ('s', mem->front()[0]);
+ EXPECT_EQ('h', mem->front()[1]);
+ EXPECT_EQ('_', mem->front()[9]);
+}
+
TEST(RefCountedMemoryUnitTest, Equals) {
std::string s1("same");
scoped_refptr<RefCountedMemory> mem1 = RefCountedString::TakeString(&s1);