forked from robotology/yarp
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy paththrift_editor.dox
155 lines (129 loc) · 4.36 KB
/
thrift_editor.dox
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
/**
*
@page thrift_editor Thrift IDL in YARP: editing structures remotely
\author Paul Fitzpatrick
Thrift offers a convenient way to define structures and services.
Structures are bundles of data, and services are bundles of methods.
Structures fit nicely into streaming communication, while
services are intended for RPC communication.
But sometimes we want to offer a set of services around a particular
structure. One recurring desire is a way to manipulate or
read just part of a structure. This is convenient if that structure
represents configuration data for a program.
With YARP, every Thrift structure has a corresponding `Editor`
service that can be used to manipulate or read parts of it.
For example, suppose we have the following structure in `settings.thrift`
\code
struct Settings {
1: i32 id;
2: string name;
3: list<i32> ints;
}
\endcode
When compiled, that will give is a `Settings` class that can read or
write from a port. That class will read the structure in full.
For example, here's a test program that will read the structure from
a port and show its value:
\code
#include <yarp/os/all.h>
#include "Settings.h"
int main() {
yarp::os::Network yarp; // bring up the yarp network
yarp::os::Port port; // we'll want a port
Settings settings; // here are the settings we'll be controlling
port.setReader(settings); // read automatically into settings
port.setCallbackLock(); // allow automatic reads to be locked
port.open("/settings"); // open port!
while(true) {
port.lockCallback(); // lock reads while we show settings
printf("Settings %s\n", settings.toString().c_str());
port.unlockCallback(); // unlock reads
Time::delay(1); // wait a little bit
}
return 0;
}
\endcode
(If you want to quickly compile this program, just put it in a file called
`<something>.cpp` in an empty directory, then add `settings.thrift`, then run
`yarp cmake && cmake . && make && ./yarpy`, specifying `-DYARP_DIR=<path_to_yarp>`
to cmake if needed.)
Once that is running, from another terminal we can write to the settings:
\verbatim
echo "1 sam (1 2 3)" | yarp write /write /settings
\endverbatim
And we see the resulting change of the entire structure:
\verbatim
yarp: Port /settings active at tcp://192.168.1.2:10002
Settings 0 "" ()
Settings 0 "" ()
Settings 1 sam (1 2 3)
...
\endverbatim
Now, suppose we want to offer a way to change parts of the structure
individually. We can make the following two-line modification:
\code
int main() {
yarp::os::Network yarp;
yarp::os::Port port;
Settings settings;
Settings::Editor editor(settings); // add an editor for settings
port.setReader(editor); // read via the editor
port.setCallbackLock();
port.open("/settings");
while(true) {
port.lockCallback();
printf("Settings %s\n", settings.toString().c_str());
port.unlockCallback();
yarp::os::Time::delay(1);
}
return 0;
}
\endcode
Now, we can send a new kind of message to the port:
\verbatim
echo 'set name "sam"' | yarp write /write /settings
\endverbatim
(It is now also possible to use `yarp rpc /settings` to send commands
and get status feedback).
Now we can see that just the part of the structure we care about will change:
\verbatim
yarp: Port /settings active at tcp://192.168.1.2:10002
Settings 0 "" ()
Settings 0 "" ()
Settings 0 sam ()
...
\endverbatim
The editor also lets us capture events generated just before and just
after a field is changed. For example, if we want to do something
just before or just after the `name` field is changed, we could do this:
\code
class MySettings : public Settings::Editor {
public:
virtual bool will_set_name() {
printf("About to set the name, it is currently '%s'\n", state().name.c_str());
}
virtual bool did_set_name() {
printf("Just set the name, it is now '%s'\n", state().name.c_str());
}
};
int main() {
yarp::os::Network yarp;
yarp::os::Port port;
Settings settings;
MySettings editor; // switch to using our custom editor
editor.edit(settings); // connect it to our settings
// ... everything else is the same ...
}
\endcode
Now if we send a message to change the `name` field, we'll see:
\verbatim
yarp: Port /settings active at tcp://192.168.1.2:10002
Settings 0 "" ()
Settings 0 "" ()
About to set the name, it is currently ''
Just set the name, it is now 'sam'
Settings 0 sam ()
...
\endverbatim
*
**/