Skip to content

Commit 40d939a

Browse files
motiz88facebook-github-bot
authored andcommitted
WeakList: add anyOf + const-propagating forEach (facebook#55313)
Summary: Changelog: [Internal] TSIA - minor refactor for convenience and correctness. NOTE: When we get C++23, we can deduplicate the identical const/non-const method bodies using the nifty [deducing `this`](https://en.cppreference.com/w/cpp/language/member_functions.html#Explicit_object_member_functions) feature. Reviewed By: hoxyq Differential Revision: D91140490
1 parent fe5d02f commit 40d939a

3 files changed

Lines changed: 93 additions & 4 deletions

File tree

packages/react-native/ReactCommon/jsinspector-modern/HostTarget.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ folly::dynamic createHostMetadataPayload(const HostTargetMetadata& metadata) {
376376

377377
bool HostTarget::hasActiveSessionWithFuseboxClient() const {
378378
bool hasActiveFuseboxSession = false;
379-
sessions_.forEach([&](HostTargetSession& session) {
379+
sessions_.forEach([&](auto& session) {
380380
hasActiveFuseboxSession |= session.hasFuseboxClient();
381381
});
382382
return hasActiveFuseboxSession;
@@ -385,7 +385,7 @@ bool HostTarget::hasActiveSessionWithFuseboxClient() const {
385385
void HostTarget::emitTracingProfileForFirstFuseboxClient(
386386
tracing::HostTracingProfile tracingProfile) {
387387
bool emitted = false;
388-
sessions_.forEach([&](HostTargetSession& session) {
388+
sessions_.forEach([&](auto& session) {
389389
if (emitted) {
390390
/**
391391
* HostTracingProfile object is not copiable for performance reasons,

packages/react-native/ReactCommon/jsinspector-modern/WeakList.h

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class WeakList {
3030
* to destroyed elements) will be removed during iteration.
3131
*/
3232
template <typename Fn>
33-
void forEach(Fn &&fn) const
33+
void forEach(Fn &&fn)
3434
{
3535
for (auto it = ptrs_.begin(); it != ptrs_.end();) {
3636
if (auto ptr = it->lock()) {
@@ -42,6 +42,65 @@ class WeakList {
4242
}
4343
}
4444

45+
/**
46+
* Call the given function for every element in the list, ensuring the element
47+
* is not destroyed for the duration of the call. Elements are visited in the
48+
* order they were inserted.
49+
*
50+
* As a side effect, any null pointers in the underlying list (corresponding
51+
* to destroyed elements) will be removed during iteration.
52+
*/
53+
template <typename Fn>
54+
void forEach(Fn &&fn) const
55+
{
56+
for (auto it = ptrs_.cbegin(); it != ptrs_.cend();) {
57+
if (auto ptr = it->lock()) {
58+
fn(*ptr);
59+
++it;
60+
} else {
61+
it = ptrs_.erase(it);
62+
}
63+
}
64+
}
65+
66+
/**
67+
* Returns true if the given function returns true for any element in the
68+
* list, ensuring the element is not destroyed for the duration of the call.
69+
*
70+
* As a side effect, any null pointers in the underlying list (corresponding
71+
* to destroyed elements) will be removed during iteration.
72+
*/
73+
template <typename Fn>
74+
bool anyOf(Fn &&fn)
75+
{
76+
bool found = false;
77+
forEach([&](auto &element) {
78+
if (!found && fn(element)) {
79+
found = true;
80+
}
81+
});
82+
return found;
83+
}
84+
85+
/**
86+
* Returns true if the given function returns true for any element in the
87+
* list, ensuring the element is not destroyed for the duration of the call.
88+
*
89+
* As a side effect, any null pointers in the underlying list (corresponding
90+
* to destroyed elements) will be removed during iteration.
91+
*/
92+
template <typename Fn>
93+
bool anyOf(Fn &&fn) const
94+
{
95+
bool found = false;
96+
forEach([&](const auto &element) {
97+
if (!found && fn(element)) {
98+
found = true;
99+
}
100+
});
101+
return found;
102+
}
103+
45104
/**
46105
* Returns the number of (non-null) elements in the list. The count will only
47106
* remain accurate as long as the list is not modified and elements are

packages/react-native/ReactCommon/jsinspector-modern/tests/WeakListTest.cpp

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ TEST(WeakListTest, ForEach) {
7070
EXPECT_THAT(visited, ElementsAre(1, 3));
7171
}
7272

73-
TEST(WeakListTest, ElementsAreAliveDuringCallback) {
73+
TEST(WeakListTest, ElementsAreAliveDuringForEachCallback) {
7474
WeakList<int> list;
7575
auto p1 = std::make_shared<int>(1);
7676
// A separate weak_ptr to observe the lifetime of `p1`.
@@ -88,4 +88,34 @@ TEST(WeakListTest, ElementsAreAliveDuringCallback) {
8888
EXPECT_THAT(visited, ElementsAre(1));
8989
}
9090

91+
TEST(WeakListTest, AnyOf) {
92+
WeakList<int> list;
93+
auto p1 = std::make_shared<int>(1);
94+
auto p2 = std::make_shared<int>(2);
95+
auto p3 = std::make_shared<int>(3);
96+
list.insert(p1);
97+
list.insert(p2);
98+
list.insert(p3);
99+
100+
EXPECT_TRUE(list.anyOf([](const int& value) { return value == 2; }));
101+
EXPECT_FALSE(list.anyOf([](const int& value) { return value == 4; }));
102+
}
103+
104+
TEST(WeakListTest, ElementsAreAliveDuringAnyOfCallback) {
105+
WeakList<int> list;
106+
auto p1 = std::make_shared<int>(42);
107+
// A separate weak_ptr to observe the lifetime of `p1`.
108+
std::weak_ptr wp1 = p1;
109+
list.insert(p1);
110+
111+
bool result = list.anyOf([&](const int& value) {
112+
p1.reset();
113+
EXPECT_FALSE(wp1.expired());
114+
return value == 42;
115+
});
116+
117+
EXPECT_TRUE(result);
118+
EXPECT_TRUE(wp1.expired());
119+
}
120+
91121
} // namespace facebook::react::jsinspector_modern

0 commit comments

Comments
 (0)