[reland] Add allow_reentrancy parameter to ObserverList
Certain client code wants to make sure that no loop is
performed while looping to avoid unexpected behaivor.
Use this new parameter to check this condition in debug build & unit tests.
Introduced ReentrantObserverList (which is currently same as defualt)
to replace the ones that indeed have to be reentrant in a separate CL.
BUG=812109
TEST=Covered by unittests
Reviewed-on: https://chromium-review.googlesource.com/915441
Commit-Queue: Mitsuru Oshima <[email protected]>
Reviewed-by: Daniel Cheng <[email protected]>
Reviewed-by: Wez <[email protected]>
Cr-Original-Commit-Position: refs/heads/master@{#537949}
Change-Id: Id4e3d04802f247491b39585219482648733b2563
Reviewed-on: https://chromium-review.googlesource.com/939530
Cr-Commit-Position: refs/heads/master@{#539698}
diff --git a/base/observer_list_unittest.cc b/base/observer_list_unittest.cc
index 9cbb168..8575bc7 100644
--- a/base/observer_list_unittest.cc
+++ b/base/observer_list_unittest.cc
@@ -23,6 +23,7 @@
#include "base/test/scoped_task_environment.h"
#include "base/threading/platform_thread.h"
#include "base/threading/thread_restrictions.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace base {
@@ -1227,4 +1228,52 @@
EXPECT_EQ(-10, b.total);
}
+class MockLogAssertHandler {
+ public:
+ MOCK_METHOD4(
+ HandleLogAssert,
+ void(const char*, int, const base::StringPiece, const base::StringPiece));
+};
+
+#if DCHECK_IS_ON()
+TEST(ObserverListTest, NonReentrantObserverList) {
+ using ::testing::_;
+
+ ObserverList<Foo, /*check_empty=*/false, /*allow_reentrancy=*/false>
+ non_reentrant_observer_list;
+ Adder a(1);
+ non_reentrant_observer_list.AddObserver(&a);
+
+ ::testing::StrictMock<MockLogAssertHandler> handler;
+ EXPECT_CALL(handler, HandleLogAssert(_, _, _, _)).Times(1);
+ {
+ logging::ScopedLogAssertHandler scoped_handler_b(base::BindRepeating(
+ &MockLogAssertHandler::HandleLogAssert, base::Unretained(&handler)));
+ for (const Foo& a : non_reentrant_observer_list) {
+ for (const Foo& b : non_reentrant_observer_list) {
+ std::ignore = a;
+ std::ignore = b;
+ }
+ }
+ }
+}
+
+TEST(ObserverListTest, ReentrantObserverList) {
+ using ::testing::_;
+
+ ReentrantObserverList<Foo> reentrant_observer_list;
+ Adder a(1);
+ reentrant_observer_list.AddObserver(&a);
+ bool passed = false;
+ for (const Foo& a : reentrant_observer_list) {
+ for (const Foo& b : reentrant_observer_list) {
+ std::ignore = a;
+ std::ignore = b;
+ passed = true;
+ }
+ }
+ EXPECT_TRUE(passed);
+}
+#endif
+
} // namespace base