A thread-safe event-listener template and observable value implementation for C++17.
The core API is best illustrated by an example.
#include <string>
#include <iostream>
#include <observe/event.h>
void example() {
// events can be valueless
observe::Event<> eventA;
// or have arguments
observe::Event<std::string, float> eventB;
// connect will always trigger when an event is triggered
eventA.connect([](){
std::cout << "A triggered" << std::endl;
});
// observers will remove themselves from the event on destroy or reset
observe::Observer observer = eventB.createObserver([](const std::string &str, float v){
std::cout << "B triggered with " << str << " and " << v << std::endl;
});
// call emit to trigger all observers
eventA.emit();
eventB.emit("meaning of life", 42);
// `observe::Observer` can store any type of observer
// previous observers will be removed
observer.observe(eventA, [](){ std::cout << "I am now observing A" << std::endl; });
// to remove an observer without destroying the object, call reset
observer.reset();
}
Note that events and observers are thread and exception safe, as long as the handlers manage their own resources.
Handlers can safely remove observers (including themselves) from the event when beeing called.
Thrown exceptions will propagate out of the event.emit()
call.
The project also includes a header observe/value.h
with an experimental observable value implementation.
The API is still subject to change, so use with caution.
observe::Value a = 1;
observe::Value b = 2;
// contains the sum of `a` and `b`
observe::DependentObservableValue sum([](auto a, auto b){ return a+b; },a,b);
// all observable values contain an `Event` `onChange`
sum.onChange.connect([](auto &v){
std::cout << "The result changed to " << r << std::endl;
});
// access the value by dereferencing
std::cout << "The result is " << *sum << std::endl; // -> the result is 3
// changes will automatically propagate through dependent values
a.set(3); // -> The result changed to 5
With CPM.cmake you can easily add the headers to your project.
CPMAddPackage(
NAME Observe
VERSION 3.0
GITHUB_REPOSITORY TheLartians/Observe
)
target_link_libraries(myProject Observe)