Skip to content

Commit ab63798

Browse files
committed
Rework recursion example
1 parent a231ec1 commit ab63798

File tree

2 files changed

+36
-20
lines changed

2 files changed

+36
-20
lines changed

examples/GuardedVectorExample.cpp

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,17 @@
77
#include <BadAccessGuards.h>
88
#include <vector>
99
#include "GuardedVectorExample.h"
10+
#include <functional>
1011

11-
struct RecursiveBehaviour {
12-
ExampleGuardedVector<RecursiveBehaviour>& vectorRef;
13-
int& valueRef;
14-
RecursiveBehaviour(ExampleGuardedVector<RecursiveBehaviour>& v, int& value)
15-
: vectorRef(v)
16-
, valueRef(value)
17-
{
18-
}
19-
20-
~RecursiveBehaviour()
12+
// Simulate any kind of event system where one may register and trigger delegates
13+
static std::vector<std::function<void()>> gEventDelegates;
14+
static void TriggerEvent()
15+
{
16+
for (const auto& delegate : gEventDelegates)
2117
{
22-
// This is something that sometimes happen when you have a lot of callbacks...
23-
// Things will try to use the container they are being removed from,
24-
// which is sometimes fine, but most often dangerous.
25-
// Here we're doing a read, but it could be something adding an element !
26-
valueRef += vectorRef.size();
18+
delegate();
2719
}
28-
};
20+
}
2921

3022
int main()
3123
{
@@ -38,10 +30,26 @@ int main()
3830
int accum = 0; // Variable to avoid optimizations
3931

4032
{
41-
ExampleGuardedVector<RecursiveBehaviour> v;
42-
printf("Testing read during write on the same thread, output:\n");
43-
v.push_back({ v, accum });
44-
v.clear();
33+
printf("\nTesting write during write on the same thread, output:\n");
34+
// A class that somehow triggers the event on construction
35+
struct RecursiveBehaviour
36+
{
37+
RecursiveBehaviour()
38+
{
39+
// You are actually inside the `ExampleGuardedVector::emplace_back()`!
40+
TriggerEvent();
41+
}
42+
};
43+
44+
ExampleGuardedVector<RecursiveBehaviour> vector;
45+
// Somewhere you setup a delegate function clearing the vector
46+
gEventDelegates.push_back([&]() {
47+
vector.clear();
48+
});
49+
50+
// Then you add some item that triggers the event delegates (could be a signal, event, etc...)
51+
// The issue is that while modifying the vector itself (you're building the item inside it!), you're also asking to clear it (due to the delegate).
52+
vector.emplace_back();
4553
}
4654

4755
using namespace std::chrono_literals;

examples/GuardedVectorExample.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@ class ExampleGuardedVector : public std::vector<T>
5555
super::push_back(std::move(val));
5656
}
5757

58+
template <class... _Valty>
59+
decltype(auto) emplace_back(_Valty&&... _Val)
60+
{
61+
BA_GUARD_WRITE(BAShadow);
62+
return super::emplace_back(std::forward<_Valty>(_Val)...);
63+
}
64+
65+
5866
T* data()
5967
{
6068
BA_GUARD_READ(BAShadow);

0 commit comments

Comments
 (0)