forked from snakster/cpp.react
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBasicObservers.cpp
More file actions
188 lines (143 loc) · 5.17 KB
/
BasicObservers.cpp
File metadata and controls
188 lines (143 loc) · 5.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
// Copyright Sebastian Jeckel 2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <iostream>
#include <string>
#include <utility>
#include "react/Domain.h"
#include "react/Signal.h"
#include "react/Event.h"
#include "react/Observer.h"
///////////////////////////////////////////////////////////////////////////////////////////////////
/// Example 1 - Creating subject-bound observers
///////////////////////////////////////////////////////////////////////////////////////////////////
namespace example1
{
using namespace std;
using namespace react;
REACTIVE_DOMAIN(D, sequential)
USING_REACTIVE_DOMAIN(D)
auto x = MakeVar<D>(1);
namespace v1
{
void Run()
{
cout << "Example 1 - Creating subject-bound observers (v1)" << endl;
{
// Create a signal in the function scope
auto mySignal = MakeSignal(x, [] (int x) { return x; } );
// The lifetime of the observer is bound to mySignal.
// After Run() returns, mySignal is destroyed, and so is the observer
Observe(mySignal, [] (int mySignal) {
cout << mySignal << endl;
});
x <<= 2; // output: 2
}
x <<= 3; // no ouput
cout << endl;
}
}
namespace v2
{
void Run()
{
cout << "Example 1 - Creating subject-bound observers (v2)" << endl;
// Outer scope
{
// Unbound observer
ObserverT obs;
// Inner scope
{
auto mySignal = MakeSignal(x, [] (int x) { return x; } );
// Move-assign to obs
obs = Observe(mySignal, [] (int mySignal) {
cout << mySignal << endl;
});
// The node linked to mySignal is now also owned by obs
x <<= 2; // output: 2
}
// ~Inner scope
// mySignal was destroyed, but as long as obs exists and is still
// attached to the signal node, this signal node won't be destroyed
x <<= 3; // output: 3
}
// ~Outer scope
// obs was destroyed
// -> the signal node is no longer owned by anything and is destroyed
// -> the observer node is destroyed as it was bound to the subject
x <<= 4; // no ouput
cout << endl;
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
/// Example 2 - Detaching observers manually
///////////////////////////////////////////////////////////////////////////////////////////////////
namespace example2
{
using namespace std;
using namespace react;
REACTIVE_DOMAIN(D, sequential)
USING_REACTIVE_DOMAIN(D)
EventSourceT<> trigger = MakeEventSource<D>();
void Run()
{
cout << "Example 2 - Detaching observers manually" << endl;
ObserverT obs = Observe(trigger, [] (Token) {
cout << "Triggered!" << endl;
});
trigger.Emit(); // output: Triggered!
obs.Detach(); // Remove the observer
trigger.Emit(); // no output
cout << endl;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
/// Example 3 - Using scoped observers
///////////////////////////////////////////////////////////////////////////////////////////////////
namespace example3
{
using namespace std;
using namespace react;
REACTIVE_DOMAIN(D, sequential)
USING_REACTIVE_DOMAIN(D)
EventSourceT<> trigger = MakeEventSource<D>();
void Run()
{
cout << "Example 3 - Using scoped observers" << endl;
// Inner scope
{
ScopedObserverT scopedObs
(
Observe(trigger, [] (Token) {
cout << "Triggered!" << endl;
})
);
trigger.Emit(); // output: Triggered!
}
// ~Inner scope
trigger.Emit(); // no output
// Note the semantic difference between ScopedObserverT and ObserverT.
//
// During its lifetime, the ObserverT handle of an observer guarantees that the
// observed subject will not be destroyed and allows explicit detach.
// But even after the ObserverT handle is destroyed, the subject may continue to exist
// and so will the observer.
//
// ScopedObserverT has similar semantics to a scoped lock.
// When it's destroyed, it detaches and destroys the observer.
cout << endl;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
/// Run examples
///////////////////////////////////////////////////////////////////////////////////////////////////
int main()
{
example1::v1::Run();
example1::v2::Run();
example2::Run();
example3::Run();
return 0;
}