EDK: Add HandleTable::AddHandleVector().
It'll replace AddDispatcherVector(), but there's a bunch of other work
needed before that can happen.
R=azani@chromium.org
Review URL: https://codereview.chromium.org/1949153002 .
diff --git a/mojo/edk/system/handle.h b/mojo/edk/system/handle.h
index 62218ce..df7fac2 100644
--- a/mojo/edk/system/handle.h
+++ b/mojo/edk/system/handle.h
@@ -5,6 +5,8 @@
#ifndef MOJO_EDK_SYSTEM_HANDLE_H_
#define MOJO_EDK_SYSTEM_HANDLE_H_
+#include <vector>
+
#include "mojo/edk/util/ref_ptr.h"
#include "mojo/public/c/system/handle.h"
@@ -42,6 +44,8 @@
MojoHandleRights rights;
};
+using HandleVector = std::vector<Handle>;
+
} // namespace system
} // namespace mojo
diff --git a/mojo/edk/system/handle_table.cc b/mojo/edk/system/handle_table.cc
index 90da427..7bff6f3 100644
--- a/mojo/edk/system/handle_table.cc
+++ b/mojo/edk/system/handle_table.cc
@@ -83,6 +83,33 @@
: std::make_pair(MOJO_HANDLE_INVALID, MOJO_HANDLE_INVALID);
}
+bool HandleTable::AddHandleVector(HandleVector* handles,
+ MojoHandle* handle_values) {
+ size_t max_message_num_handles = GetConfiguration().max_message_num_handles;
+
+ DCHECK(handles);
+ DCHECK_LE(handles->size(), max_message_num_handles);
+ DCHECK(handle_values);
+ DCHECK_LT(
+ static_cast<uint64_t>(max_handle_table_size_) + max_message_num_handles,
+ std::numeric_limits<size_t>::max())
+ << "Addition may overflow";
+
+ if (handle_to_entry_map_.size() + handles->size() > max_handle_table_size_)
+ return false;
+
+ for (size_t i = 0; i < handles->size(); i++) {
+ if (handles->at(i)) {
+ handle_values[i] = AddHandleNoSizeCheck(std::move(handles->at(i)));
+ } else {
+ LOG(WARNING) << "Invalid dispatcher at index " << i;
+ handle_values[i] = MOJO_HANDLE_INVALID;
+ }
+ }
+ return true;
+}
+
+// TODO(vtl): Delete this.
bool HandleTable::AddDispatcherVector(const DispatcherVector& dispatchers,
MojoHandle* handles) {
size_t max_message_num_handles = GetConfiguration().max_message_num_handles;
diff --git a/mojo/edk/system/handle_table.h b/mojo/edk/system/handle_table.h
index 19b3aa5..4cdbd36 100644
--- a/mojo/edk/system/handle_table.h
+++ b/mojo/edk/system/handle_table.h
@@ -74,12 +74,15 @@
std::pair<MojoHandle, MojoHandle> AddHandlePair(Handle&& handle0,
Handle&& handle1);
- // Adds the given vector of dispatchers (of size at most
+ // Adds the given vector of handles (of size at most
// |kMaxMessageNumHandles|). |handle_values| must point to an array of size at
- // least |dispatchers.size()|. Unlike the other |AddDispatcher...()|
- // functions, some of the dispatchers may be invalid (null). Returns true on
- // success and false on failure (if the handle table is full), in which case
- // it leaves |handle_values[...]| untouched (and all dispatchers unadded).
+ // least |handles->size()|. Unlike the other |AddHandle...()| functions, some
+ // of the handles may be invalid ("null"). Returns true on success in which
+ // case all the handles in |*handles| are moved from, and false on failure (if
+ // the handle table is full), in which case it leaves all |handles->at(...)||
+ // (and all the handles unadded) and |handle_values[...]| untouched.
+ bool AddHandleVector(HandleVector* handles, MojoHandle* handle_values);
+ // TODO(vtl): Delete this version (use |AddHandleVector()| instead).
bool AddDispatcherVector(const DispatcherVector& dispatchers,
MojoHandle* handle_values);
diff --git a/mojo/edk/system/handle_table_unittest.cc b/mojo/edk/system/handle_table_unittest.cc
index a239962..33c983d 100644
--- a/mojo/edk/system/handle_table_unittest.cc
+++ b/mojo/edk/system/handle_table_unittest.cc
@@ -4,6 +4,8 @@
#include "mojo/edk/system/handle_table.h"
+#include <vector>
+
#include "mojo/edk/system/dispatcher.h"
#include "mojo/edk/system/handle.h"
#include "mojo/edk/system/mock_simple_dispatcher.h"
@@ -175,6 +177,73 @@
EXPECT_EQ(MOJO_RESULT_OK, d4->Close());
}
+TEST(HandleTableTest, AddHandleVector) {
+ static constexpr size_t kNumHandles = 10u;
+
+ HandleTable ht(1000u);
+
+ HandleVector handles;
+ std::vector<RefPtr<Dispatcher>> dispatchers;
+ for (size_t i = 0u; i < kNumHandles; i++) {
+ dispatchers.push_back(MakeRefCounted<test::MockSimpleDispatcher>());
+ handles.push_back(
+ Handle(dispatchers.back().Clone(), MOJO_HANDLE_RIGHT_NONE));
+ ASSERT_TRUE(handles[i]) << i;
+ }
+
+ std::vector<MojoHandle> handle_values(kNumHandles, MOJO_HANDLE_INVALID);
+
+ ASSERT_TRUE(ht.AddHandleVector(&handles, handle_values.data()));
+
+ for (size_t i = 0u; i < kNumHandles; i++) {
+ ASSERT_NE(handle_values[i], MOJO_HANDLE_INVALID) << i;
+
+ RefPtr<Dispatcher> d;
+ ASSERT_EQ(MOJO_RESULT_OK, ht.GetAndRemoveDispatcher(handle_values[i], &d))
+ << i;
+ ASSERT_EQ(dispatchers[i], d) << i;
+
+ EXPECT_EQ(MOJO_RESULT_OK, dispatchers[i]->Close()) << i;
+ }
+}
+
+TEST(HandleTableTest, AddHandleVectorTooMany) {
+ static constexpr size_t kHandleTableSize = 10u;
+ static constexpr size_t kNumHandles = kHandleTableSize + 1u;
+
+ HandleTable ht(kHandleTableSize);
+
+ HandleVector handles;
+ std::vector<RefPtr<Dispatcher>> dispatchers;
+ for (size_t i = 0u; i < kNumHandles; i++) {
+ dispatchers.push_back(MakeRefCounted<test::MockSimpleDispatcher>());
+ handles.push_back(
+ Handle(dispatchers.back().Clone(), MOJO_HANDLE_RIGHT_NONE));
+ ASSERT_TRUE(handles[i]) << i;
+ }
+
+ std::vector<MojoHandle> handle_values(kNumHandles, MOJO_HANDLE_INVALID);
+
+ EXPECT_FALSE(ht.AddHandleVector(&handles, handle_values.data()));
+
+ handles.pop_back();
+ handle_values.pop_back();
+
+ ASSERT_TRUE(ht.AddHandleVector(&handles, handle_values.data()));
+
+ for (size_t i = 0u; i < kNumHandles - 1u; i++) {
+ ASSERT_NE(handle_values[i], MOJO_HANDLE_INVALID) << i;
+
+ RefPtr<Dispatcher> d;
+ ASSERT_EQ(MOJO_RESULT_OK, ht.GetAndRemoveDispatcher(handle_values[i], &d))
+ << i;
+ ASSERT_EQ(dispatchers[i], d) << i;
+ }
+
+ for (size_t i = 0u; i < kNumHandles; i++)
+ EXPECT_EQ(MOJO_RESULT_OK, dispatchers[i]->Close()) << i;
+}
+
} // namespace
} // namespace system
} // namespace mojo