How-To Monitor Property Changes
Because wyrd can be used in distributed systems, it’s possible for another software/agent to update a property. That means it may be of interest to monitor a property for change.
To do this, you need to create a callback function and register it with the document handle for a particular property path.
1void my_callback(struct wyrd_handle * handle, char const * path, wyrd_property_type type,
2 void const * value, size_t value_size, void * baton)
3{
4 // ...
5}
The callback receives the document handle, as well as the property path that has been changed. The next parameter is the new property type after modification, as well as the value pointer (and its size).
You will have to cast the value pointer to something appropriate for the type to work with it. The simple example below only accepts a single type; you can expand on this example.
1void my_callback(struct wyrd_handle * handle, char const * path, wyrd_property_type type,
2 void const * value, size_t value_size, void * baton)
3{
4 if (WYRD_PT_UINT16 != type || value_size != sizeof(uint16_t)) {
5 return;
6 }
7
8 uint16_t val = *((uint16_t const *) value);
9 // ...
10}
You can now register this callback.
1wyrd_error_t err = wyrd_add_property_callback(handle, ".foo", my_callback, NULL);
That last parameter, here set to NULL, gets handed to the callback as the baton argument.
Callback Loops
It is perfectly possible for your callback to modify the property for which it is getting invoked. But be aware that there is no protection against callback loops here. That is, if you register the callback for a path, and modify the same path again, then the callback will be invoked again.
Let’s assume we want a property to only contain even numbers for some reason. We can use a callback to monitor the property, and if the value is odd, we set it to the next lowest even number instead.
1void my_callback(struct wyrd_handle * handle, char const * path, wyrd_property_type type,
2 void const * value, size_t value_size, void * baton)
3{
4 fprintf(stderr, "my_callback() called.\n");
5
6 if (WYRD_PT_UINT16 != type || value_size != sizeof(uint16_t)) {
7 return;
8 }
9
10 uint16_t val = *((uint16_t const *) value);
11 if (val % 2) {
12 --val;
13
14 wyrd_set_property_uint16(handle, path, WYRD_MS_NAIVE_OVERRIDE, val);
15 }
16}
If you now set this property to an even number, you will see by the debug line that it will get invoked once. If you set it to an odd number, it will get invoked twice.
First, it will be called because you set the odd number. This then enters the if-statement in the callback, which reduces the value by one, and overwrites it. That triggers the callback a second time.
On the second invocation, however, the if-block is not executed.
Warning
Be careful when modifying properties from within a callback; you may have to explicitly avoid callback loops.