Skip to content

Commit b193801

Browse files
committed
Container/SafeShared: Code cleaning
1 parent a3a20d7 commit b193801

11 files changed

Lines changed: 112 additions & 93 deletions

File tree

modules/Container/Container.mpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export import CppUtils.Container.DependencyGraph;
66
export import CppUtils.Container.MeshNetwork;
77
export import CppUtils.Container.NetworkPtr;
88
export import CppUtils.Container.Pair;
9+
export import CppUtils.Container.SafeShared;
910
export import CppUtils.Container.Sequence;
1011
export import CppUtils.Container.Size2d;
1112
export import CppUtils.Container.Size3d;

modules/Container/MeshNetwork.mpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
export module CppUtils.Container.MeshNetwork;
22

33
import std;
4-
import CppUtils.Thread.SharedLocker;
54
import CppUtils.Container.NetworkPtr;
5+
import CppUtils.Container.SafeShared;
6+
import CppUtils.Thread.SharedLocker;
67

78
export namespace CppUtils::Container
89
{
@@ -29,7 +30,7 @@ export namespace CppUtils::Container
2930
auto& branches = node0Accessor->value.branches;
3031
auto& childs = branches[key1];
3132
if (auto it = std::find_if(std::cbegin(childs), std::cend(childs), [&](const auto& child) -> bool {
32-
return std::shared_ptr{child} == node1;
33+
return SafeShared{child} == node1;
3334
});
3435
it != std::cend(childs))
3536
childs.erase(it);

modules/Container/NetworkPtr.mpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export module CppUtils.Container.NetworkPtr;
22

33
import std;
4+
import CppUtils.Container.SafeShared;
45
import CppUtils.Thread.SharedLocker;
56
import CppUtils.Thread.SharedPtr;
67

@@ -11,8 +12,8 @@ export namespace CppUtils::Container
1112
{
1213
public:
1314
using Value = T;
14-
using SharedPtr = std::shared_ptr<Thread::SharedLocker<NetworkPtr<T>>>;
15-
using WeakPtr = std::weak_ptr<Thread::SharedLocker<NetworkPtr<T>>>;
15+
using SharedPtr = SafeShared<NetworkPtr<T>>;
16+
using WeakPtr = SafeWeak<NetworkPtr<T>>;
1617

1718
private:
1819
explicit inline NetworkPtr(auto&&... args):
@@ -30,7 +31,7 @@ export namespace CppUtils::Container
3031

3132
[[nodiscard]] static inline auto make(auto&&... args) -> SharedPtr
3233
{
33-
auto ptr = std::make_shared<Thread::SharedLocker<NetworkPtr<T>>>(std::forward<decltype(args)>(args)...);
34+
auto ptr = makeSafeShared<NetworkPtr<T>>(std::forward<decltype(args)>(args)...);
3435
{
3536
auto accessor = ptr->uniqueAccess();
3637
accessor->setWeakThis(ptr);
@@ -40,7 +41,7 @@ export namespace CppUtils::Container
4041

4142
[[nodiscard]] static inline auto makeRoot(auto&&... args) -> SharedPtr
4243
{
43-
auto ptr = std::make_shared<Thread::SharedLocker<NetworkPtr<T>>>(std::forward<decltype(args)>(args)...);
44+
auto ptr = makeSafeShared<NetworkPtr<T>>(std::forward<decltype(args)>(args)...);
4445
{
4546
auto accessor = ptr->uniqueAccess();
4647
accessor->setWeakThis(ptr);
@@ -66,9 +67,9 @@ export namespace CppUtils::Container
6667
m_distanceFromRoot = 0;
6768
}
6869

69-
inline auto setWeakThis(const WeakPtr& ptr) -> void
70+
inline auto setWeakThis(WeakPtr ptr) -> void
7071
{
71-
m_weak_this = ptr;
72+
m_weak_this = std::move(ptr);
7273
}
7374

7475
[[nodiscard]] inline auto getDistanceFromRoot() const -> std::size_t
@@ -89,7 +90,7 @@ export namespace CppUtils::Container
8990
if (childAccessor->m_distanceFromRoot > m_distanceFromRoot)
9091
m_children.push_back(childPtr);
9192
else
92-
m_children.push_back(std::weak_ptr{childPtr});
93+
m_children.push_back(SafeWeak{childPtr});
9394
childAccessor->m_parents.push_back(m_weak_this);
9495
}
9596

@@ -161,7 +162,7 @@ export namespace CppUtils::Container
161162
if (std::holds_alternative<SharedPtr>(child))
162163
sharedPtr = std::get<SharedPtr>(child);
163164
else
164-
sharedPtr = std::shared_ptr{std::get<WeakPtr>(child)};
165+
sharedPtr = SharedPtr{std::get<WeakPtr>(child)};
165166
return sharedPtr->uniqueAccess();
166167
}
167168

modules/Container/SafeShared.mpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
export module CppUtils.Container.SafeShared;
2+
3+
import std;
4+
import CppUtils.Thread.SharedLocker;
5+
import CppUtils.Thread.SharedPtr;
6+
7+
export namespace CppUtils::Container
8+
{
9+
template<class T>
10+
using SafeShared = std::shared_ptr<Thread::SharedLocker<T>>;
11+
12+
template<class T>
13+
inline auto makeSafeShared(auto&&... args) -> SafeShared<T>
14+
{
15+
return SafeShared{std::make_shared<Thread::SharedLocker<T>>(std::forward<decltype(args)>(args)...)};
16+
}
17+
18+
template<class T>
19+
using SafeWeak = std::weak_ptr<Thread::SharedLocker<T>>;
20+
}

modules/Thread/SafeShared.mpp

Lines changed: 0 additions & 29 deletions
This file was deleted.

modules/Thread/SharedPtr.mpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,13 @@ import std;
44

55
export namespace CppUtils::Thread::SharedPtr
66
{
7-
// Sera remplacé par std::shared_ptr<T>::owner_equal en C++26
8-
[[nodiscard]] inline auto ownerEqual(const auto& lhs, const auto& rhs) -> bool
7+
[[nodiscard]] inline auto ownerEqual(const auto& lhs, const auto& rhs) noexcept -> bool
98
{
9+
// C++26: std::shared_ptr<T>::owner_equal & std::weak_ptr<T>::owner_equal
10+
#if __has_cpp_attribute(__cpp_lib_smart_ptr_owner_equality)
11+
return lhs.owner_equal(rhs);
12+
#else
1013
return not lhs.owner_before(rhs) and not rhs.owner_before(lhs);
14+
#endif
1115
}
1216
}

modules/Thread/Thread.mpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ export module CppUtils.Thread;
22

33
export import CppUtils.Thread.AsyncIStreamListener;
44
export import CppUtils.Thread.Event;
5-
export import CppUtils.Thread.SafeShared;
65
export import CppUtils.Thread.SharedLocker;
76
export import CppUtils.Thread.SharedPtr;
87
export import CppUtils.Thread.ThreadLoop;

tests/Container/MeshNetwork.mpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export namespace CppUtils::UnitTest::Container::MeshNetwork
2222
});
2323

2424
suite.addTest("Copy reference", [&] {
25-
auto appleRef = StringMeshNode::SharedPtr{};
25+
auto appleRef = CppUtils::Container::SafeShared<StringMeshNode>{};
2626
{
2727
auto apple = StringMeshNode::make("apple");
2828
appleRef = apple;
@@ -46,7 +46,7 @@ export namespace CppUtils::UnitTest::Container::MeshNetwork
4646
const auto& fruits = fruitBranches.at("Elements");
4747
suite.expect(std::size(fruits) == 1);
4848
{
49-
auto apple = std::shared_ptr{fruits[0]};
49+
auto apple = StringMeshNode::SharedPtr{fruits[0]};
5050
auto appleAccessor = apple->sharedAccess();
5151
const auto& value = appleAccessor->value.value;
5252
Logger::print("{}\n", value);
@@ -68,14 +68,14 @@ export namespace CppUtils::UnitTest::Container::MeshNetwork
6868
const auto& fruits = fruitBranches.at("Elements");
6969
suite.expect(std::size(fruits) == 2);
7070
{
71-
auto apple = std::shared_ptr{fruits[0]};
71+
auto apple = StringMeshNode::SharedPtr{fruits[0]};
7272
auto appleAccessor = apple->sharedAccess();
7373
const auto& value = appleAccessor->value.value;
7474
Logger::print("{}\n", value);
7575
suite.expect(value == "apple");
7676
}
7777
{
78-
auto banana = std::shared_ptr{fruits[1]};
78+
auto banana = StringMeshNode::SharedPtr{fruits[1]};
7979
auto bananaAccessor = banana->sharedAccess();
8080
const auto& value = bananaAccessor->value.value;
8181
Logger::print("{}\n", value);
@@ -92,7 +92,7 @@ export namespace CppUtils::UnitTest::Container::MeshNetwork
9292
const auto& fruits = fruitBranches.at("Elements");
9393
suite.expect(std::size(fruits) == 1);
9494
{
95-
auto banana = std::shared_ptr{fruits[0]};
95+
auto banana = StringMeshNode::SharedPtr{fruits[0]};
9696
auto bananaAccessor = banana->sharedAccess();
9797
const auto& value = bananaAccessor->value.value;
9898
Logger::print("{}\n", value);
@@ -123,14 +123,14 @@ export namespace CppUtils::UnitTest::Container::MeshNetwork
123123
const auto& fruits = fruitBranches.at("Elements");
124124
suite.expect(std::size(fruits) == 2);
125125
{
126-
auto apple = std::shared_ptr{fruits[0]};
126+
auto apple = StringMeshNode::SharedPtr{fruits[0]};
127127
auto appleAccessor = apple->sharedAccess();
128128
const auto& value = appleAccessor->value.value;
129129
Logger::print("{}\n", value);
130130
suite.expect(value == "apple");
131131
}
132132
{
133-
auto banana = std::shared_ptr{fruits[1]};
133+
auto banana = StringMeshNode::SharedPtr{fruits[1]};
134134
auto bananaAccessor = banana->sharedAccess();
135135
const auto& value = bananaAccessor->value.value;
136136
Logger::print("{}\n", value);
@@ -156,7 +156,7 @@ export namespace CppUtils::UnitTest::Container::MeshNetwork
156156
const auto& fruitBranches = fruitAccessor->value.branches;
157157
const auto& fruits = fruitBranches.at("Elements");
158158
suite.expect(std::size(fruits) == 1);
159-
auto firstFruit = std::shared_ptr{fruits[0]};
159+
auto firstFruit = StringMeshNode::SharedPtr{fruits[0]};
160160
auto appleAccessor = firstFruit->sharedAccess();
161161
const auto& appleName = appleAccessor->value.value;
162162
const auto& fruitName = fruitAccessor->value.value;
@@ -169,7 +169,7 @@ export namespace CppUtils::UnitTest::Container::MeshNetwork
169169
const auto& appleBranches = appleAccessor->value.branches;
170170
const auto& appleCategories = appleBranches.at("Categories");
171171
suite.expect(std::size(appleCategories) == 1);
172-
auto firstCategory = std::shared_ptr{appleCategories[0]};
172+
auto firstCategory = StringMeshNode::SharedPtr{appleCategories[0]};
173173
auto fruitAccessor = firstCategory->sharedAccess();
174174
const auto& appleName = appleAccessor->value.value;
175175
const auto& fruitName = fruitAccessor->value.value;
@@ -205,19 +205,19 @@ export namespace CppUtils::UnitTest::Container::MeshNetwork
205205
const auto& fruitBranches = fruitAccessor->value.branches;
206206
for (const auto& weakFruit : fruitBranches.at("Elements"))
207207
{
208-
auto fruit = std::shared_ptr{weakFruit};
208+
auto fruit = StringMeshNode::SharedPtr{weakFruit};
209209
auto fruitAccessor = fruit->sharedAccess();
210210
const auto& fruitBranches = fruitAccessor->value.branches;
211211

212212
const auto& fruitCategories = fruitBranches.at("Categories");
213213
suite.expect(std::size(fruitCategories) == 1);
214-
auto fruitCategory = std::shared_ptr{fruitCategories[0]};
214+
auto fruitCategory = StringMeshNode::SharedPtr{fruitCategories[0]};
215215
auto fruitCategoryAccessor = fruitCategory->sharedAccess();
216216
suite.expect(fruitCategoryAccessor->value.value == "fruit");
217217

218218
const auto& colors = fruitBranches.at("Colors");
219219
suite.expect(std::size(colors) == 1);
220-
auto color = std::shared_ptr{colors[0]};
220+
auto color = StringMeshNode::SharedPtr{colors[0]};
221221
auto colorAccessor = color->sharedAccess();
222222

223223
Logger::print("{} is a {} {}\n", fruitAccessor->value.value, colorAccessor->value.value, fruitCategoryAccessor->value.value);

tests/Container/NetworkPtr.mpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ export namespace CppUtils::UnitTest::Container::NetworkPtr
8383

8484
suite.addTest("Bilateral attachment", [&] {
8585
auto root = NetworkPtr::makeRoot("Root");
86-
auto branch = NetworkPtr::SharedPtr{};
86+
auto branch = CppUtils::Container::SafeShared<NetworkPtr>{};
8787
{
8888
branch = NetworkPtr::make("Branch", 1uz);
8989
auto rootAccessor = root->uniqueAccess();

tests/Container/SafeShared.mpp

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
export module CppUtils.UnitTests.Container.SafeShared;
2+
3+
import CppUtils;
4+
5+
export namespace CppUtils::UnitTest::Container::SafeShared
6+
{
7+
inline auto _ = CppUtils::UnitTest::TestSuite{"Container/SafeShared", {"UnitTest", "Thread/SharedLocker"}, [](auto& suite) {
8+
suite.addTest("Empty", [&] {
9+
auto safeSharedString = CppUtils::Container::SafeShared<std::string>{};
10+
11+
suite.expect(not static_cast<bool>(safeSharedString));
12+
});
13+
14+
suite.addTest("Unique access", [&] {
15+
auto safeSharedString0 = CppUtils::Container::makeSafeShared<std::string>("Foo");
16+
suite.expect(static_cast<bool>(safeSharedString0));
17+
18+
auto safeSharedString1 = safeSharedString0;
19+
{
20+
auto accessor = safeSharedString0->uniqueAccess();
21+
suite.expect(accessor.value() == "Foo");
22+
accessor.value() = "Bar";
23+
suite.expect(accessor.value() == "Bar");
24+
}
25+
{
26+
auto accessor = safeSharedString1->uniqueAccess();
27+
suite.expect(accessor.value() == "Bar");
28+
}
29+
});
30+
31+
suite.addTest("Shared access", [&] {
32+
auto safeSharedString0 = CppUtils::Container::makeSafeShared<std::string>("Foo");
33+
auto safeSharedString1 = safeSharedString0;
34+
{
35+
auto accessor0 = safeSharedString0->sharedAccess();
36+
auto accessor1 = safeSharedString0->sharedAccess();
37+
auto accessor2 = safeSharedString1->sharedAccess();
38+
auto accessor3 = safeSharedString1->sharedAccess();
39+
suite.expect(accessor0.value() == "Foo");
40+
suite.expect(accessor1.value() == "Foo");
41+
suite.expect(accessor2.value() == "Foo");
42+
suite.expect(accessor3.value() == "Foo");
43+
}
44+
});
45+
46+
suite.addTest("SafeWeak", [&] {
47+
auto safeSharedString0 = CppUtils::Container::makeSafeShared<std::string>("Foo");
48+
auto safeWeak = CppUtils::Container::SafeWeak{safeSharedString0};
49+
suite.expect(not safeWeak.expired());
50+
51+
auto safeSharedString1 = safeWeak.lock();
52+
{
53+
auto accessor0 = safeSharedString0->sharedAccess();
54+
auto accessor1 = safeSharedString1->sharedAccess();
55+
suite.expect(accessor0.value() == "Foo");
56+
suite.expect(accessor1.value() == "Foo");
57+
}
58+
});
59+
}};
60+
}

0 commit comments

Comments
 (0)