@@ -8,55 +8,85 @@ using namespace Windows::Foundation::Collections;
8
8
9
9
namespace
10
10
{
11
- bool destroyed{};
12
- int strong_count{};
13
- int weak_count{};
11
+ struct Counters
12
+ {
13
+ bool destroyed{};
14
+ int strong_count{};
15
+ int weak_count{};
16
+ int weak_lambda_count{};
17
+
18
+ bool is_count (int value)
19
+ {
20
+ return strong_count == value && weak_count == value && weak_lambda_count == value;
21
+ }
22
+ };
14
23
15
24
template <typename Sender, typename Args>
16
25
struct Object : implements<Object<Sender, Args>, IInspectable>
17
26
{
27
+ std::shared_ptr<Counters> m_counters;
28
+
29
+ Object (std::shared_ptr<Counters> const & counters) : m_counters(counters) {}
30
+
31
+ static auto make (std::shared_ptr<Counters> const & counters)
32
+ {
33
+ return make_self<Object>(counters);
34
+ }
35
+
36
+ auto strong () { return this ->get_strong (); }
37
+ auto weak () { return this ->get_weak (); }
38
+
18
39
~Object ()
19
40
{
20
- destroyed = true ;
41
+ m_counters-> destroyed = true ;
21
42
}
22
43
23
44
void StrongHandler (Sender const &, Args const &)
24
45
{
25
- ++strong_count;
46
+ REQUIRE (!m_counters->destroyed );
47
+ ++m_counters->strong_count ;
26
48
}
27
49
28
50
void WeakHandler (Sender const &, Args const &)
29
51
{
30
- ++weak_count;
52
+ REQUIRE (!m_counters->destroyed );
53
+ ++m_counters->weak_count ;
31
54
}
32
55
};
33
56
34
57
template <typename Sender, typename Args>
35
58
struct ObjectStd : std::enable_shared_from_this<ObjectStd<Sender, Args>>
36
59
{
60
+ std::shared_ptr<Counters> m_counters;
61
+
62
+ ObjectStd (std::shared_ptr<Counters> const & counters) : m_counters(counters) {}
63
+
64
+ static auto make (std::shared_ptr<Counters> const & counters)
65
+ {
66
+ return std::make_shared<ObjectStd>(counters);
67
+ }
68
+
69
+ auto strong () { return this ->shared_from_this (); }
70
+ auto weak () { return this ->weak_from_this (); }
71
+
37
72
~ObjectStd ()
38
73
{
39
- destroyed = true ;
74
+ m_counters-> destroyed = true ;
40
75
}
41
76
42
77
void StrongHandler (Sender const &, Args const &)
43
78
{
44
- ++strong_count;
79
+ ++m_counters-> strong_count ;
45
80
}
46
81
47
82
void WeakHandler (Sender const &, Args const &)
48
83
{
49
- ++weak_count;
84
+ ++m_counters-> weak_count ;
50
85
}
51
86
};
52
87
53
88
struct ReturnObject : implements<ReturnObject, IInspectable>
54
89
{
55
- ~ReturnObject ()
56
- {
57
- destroyed = true ;
58
- }
59
-
60
90
int Handler (int a, int b)
61
91
{
62
92
return a + b;
@@ -65,91 +95,63 @@ namespace
65
95
66
96
struct ReturnObjectStd : std::enable_shared_from_this<ReturnObjectStd>
67
97
{
68
- ~ReturnObjectStd ()
69
- {
70
- destroyed = true ;
71
- }
72
-
73
98
int Handler (int a, int b)
74
99
{
75
100
return a + b;
76
101
}
77
102
};
78
103
79
- template <typename Delegate , typename Sender, typename Args >
80
- void test_delegate_winrt ()
104
+ template <typename Recipient , typename Delegate >
105
+ void test_delegate_pattern ()
81
106
{
82
- auto object = make_self<Object<Sender, Args>>();
83
-
84
- Delegate strong{ object->get_strong (), &Object<Sender, Args>::StrongHandler };
85
- Delegate weak{ object->get_weak (), &Object<Sender, Args>::WeakHandler };
107
+ auto counters = std::make_shared<Counters>();
108
+ auto object = Recipient::make (counters);
86
109
87
- destroyed = false ;
88
- strong_count = 0 ;
89
- weak_count = 0 ;
110
+ Delegate strong{ object->strong (), &Recipient::StrongHandler};
111
+ Delegate weak{ object->weak (), &Recipient::WeakHandler };
112
+ Delegate weak_lambda{ object->weak (),[counters](auto &&, auto &&) {
113
+ REQUIRE (!counters->destroyed );
114
+ ++counters->weak_lambda_count ;
115
+ } };
90
116
91
- // Both weak and strong handlers
117
+ // All handlers are active at this point
92
118
strong ({}, {});
93
119
weak ({}, {});
94
- REQUIRE (strong_count == 1 );
95
- REQUIRE (weak_count == 1 );
120
+ weak_lambda ({}, {} );
121
+ REQUIRE (counters-> is_count ( 1 ) );
96
122
97
123
// Local 'object' strong reference is released
98
124
object = nullptr ;
99
125
100
- // Still both since strong handler keeps object alive
126
+ // Still invoked since strong handler keeps object alive
101
127
strong ({}, {});
102
128
weak ({}, {});
103
- REQUIRE (strong_count == 2 );
104
- REQUIRE (weak_count == 2 );
129
+ weak_lambda ({}, {} );
130
+ REQUIRE (counters-> is_count ( 2 ) );
105
131
106
- // ~Object is called since the strong delegate is destroyed
107
- REQUIRE (!destroyed);
132
+ // ~Recipient is called since the strong delegate is destroyed
133
+ REQUIRE (!counters-> destroyed );
108
134
strong = nullptr ;
109
- REQUIRE (destroyed);
135
+ REQUIRE (counters-> destroyed );
110
136
111
137
// Weak delegate remains but no longer fires
112
- REQUIRE (weak_count == 2 );
138
+ // Strong delegate shouldn't fire either
139
+ REQUIRE (counters->is_count (2 ));
113
140
weak ({}, {});
114
- REQUIRE (weak_count == 2 );
141
+ weak_lambda ({}, {});
142
+ REQUIRE (counters->is_count (2 ));
115
143
}
116
144
117
145
template <typename Delegate, typename Sender, typename Args>
118
- void test_delegate_std ()
146
+ void test_delegate_winrt ()
119
147
{
120
- auto object = std::make_shared<ObjectStd<Sender, Args>>();
121
-
122
- Delegate strong{ object->shared_from_this (), &ObjectStd<Sender, Args>::StrongHandler };
123
- Delegate weak{ object->weak_from_this (), &ObjectStd<Sender, Args>::WeakHandler };
124
-
125
- destroyed = false ;
126
- strong_count = 0 ;
127
- weak_count = 0 ;
128
-
129
- // Both weak and strong handlers
130
- strong ({}, {});
131
- weak ({}, {});
132
- REQUIRE (strong_count == 1 );
133
- REQUIRE (weak_count == 1 );
134
-
135
- // Local 'object' strong reference is released
136
- object = nullptr ;
137
-
138
- // Still both since strong handler keeps object alive
139
- strong ({}, {});
140
- weak ({}, {});
141
- REQUIRE (strong_count == 2 );
142
- REQUIRE (weak_count == 2 );
143
-
144
- // ~Object is called since the strong delegate is destroyed
145
- REQUIRE (!destroyed);
146
- strong = nullptr ;
147
- REQUIRE (destroyed);
148
+ test_delegate_pattern<Object<Sender, Args>, Delegate>();
149
+ }
148
150
149
- // Weak delegate remains but no longer fires
150
- REQUIRE (weak_count == 2 );
151
- weak ({}, {});
152
- REQUIRE (weak_count == 2 );
151
+ template < typename Delegate, typename Sender, typename Args>
152
+ void test_delegate_std ()
153
+ {
154
+ test_delegate_pattern<ObjectStd<Sender, Args>, Delegate>( );
153
155
}
154
156
155
157
template <typename Delegate, typename Sender, typename Args>
0 commit comments