Skip to content

Commit

Permalink
Merge pull request #12 from DeveloperPaul123/feature/raii-registrations
Browse files Browse the repository at this point in the history
  • Loading branch information
DeveloperPaul123 authored Oct 31, 2020
2 parents 4a347ac + 2ad8a77 commit 5418996
Show file tree
Hide file tree
Showing 5 changed files with 189 additions and 108 deletions.
4 changes: 2 additions & 2 deletions CMakeSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
},
{
"name": "WSL-Clang-Debug",
"generator": "Unix Makefiles",
"generator": "Ninja",
"configurationType": "Debug",
"buildRoot": "${projectDir}\\out\\build\\${name}",
"installRoot": "${projectDir}\\out\\install\\${name}",
Expand All @@ -41,7 +41,7 @@
},
{
"name": "WSL-GCC-Debug",
"generator": "Unix Makefiles",
"generator": "Ninja",
"configurationType": "Debug",
"buildRoot": "${projectDir}\\out\\build\\${name}",
"installRoot": "${projectDir}\\out\\install\\${name}",
Expand Down
28 changes: 19 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@

`eventbus` is a simple, header only C++17 event bus library that doesn't require you to inherit from any sort of `event` class.

- [Design Goals](#design-goals)
- [Overview](#overview)
- [Features](#features)
- [Integration](#integration)
- [CMake](#cmake)
- [vcpkg](#vcpkg)
Expand All @@ -44,16 +45,20 @@
- [Author](#author)
- [Contributors](#contributors)

## Design Goals
## Overview

`eventbus` implements the "Mediator" pattern. This pattern is useful when you want components to communicate to each other without necessarily "knowing" about each other. This can be useful in *some* situations but should be used with caution (there are alternative design patterns to consider).
`eventbus` implements the "Mediator" pattern. This pattern is useful when you want components to communicate to each other without necessarily "knowing" about each other. Effectively, this is a thread safe event dispatcher with a list of callbacks.

- **Do not require event object inheritance** I wanted to implement an event bus system that doesn't require users to inherit from some base `Event` class in order to use the event class.
- **Flexible Callback Types** It's important that the library supports a variety different types of callbacks including:
## Features

- **Does not require event object inheritance** A base `Event` class is not requied for use with `dp::event_bus`. Any class/struct can be used as an event object.
- **Flexible Callback Types** `eventbus` supports a variety different types of callbacks including:
- Lambdas
- Class member functions
- Free functions
- **Flexible Callbacks** Callbacks should be able to take no input parameters, the event type by `const&` or by value.
- **Flexible Callbacks** No parameter callbacks are also supported as well as taking the event type by value or by `const &`.
- **RAII de-registrations** The handler registration objects automatically de-register the handler upon destruction.
- **Thread safety** Multiple threads can fire events at once to the same `event_bus`. Handlers can also be registered from different threads.

## Integration

Expand Down Expand Up @@ -105,14 +110,14 @@ void event_callback(event_type evt)
}

dp::event_bus evt_bus;
evt_bus.register_handler<event_type>(&event_callback)
const auto registration_handler = evt_bus.register_handler<event_type>(&event_callback)
````
#### Lambda
````cpp
dp::event_bus evt_bus;
evt_bus.register_handler<event_type>([](const event_type& evt)
const auto registration_handler = evt_bus.register_handler<event_type>([](const event_type& evt)
{
// logic code...
});
Expand All @@ -133,7 +138,7 @@ class event_handler
// other code
dp::event_bus evt_bus;
event_handler handler;
evt_bus.register_handler<event_type>(&handler, &event_handler::on_event);
const auto registration_handler = evt_bus.register_handler<event_type>(&handler, &event_handler::on_event);
````

**Note:** You can't mix a class instance of type `T` with the member function of another class (i.e. `&U::function_name`).
Expand All @@ -155,6 +160,11 @@ A complete example can be seen in the [demo](https://github.com/DeveloperPaul123

In general, all callback functions **must** return `void`. Currently, `eventbus` only supports single argument functions as callbacks.

The following use cases are not supported:

- Registering a callback inside an event callback.
- De-registering a callback inside an event callback.

## Contributing

If you find an issue with this library please file an [issue](https://github.com/DeveloperPaul123/eventbus/issues). Pull requests are also welcome! Please see the [contribution guidelines](CONTRIBUTING.md) for more information.
Expand Down
25 changes: 12 additions & 13 deletions demo/main.cpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
#include <iostream>
#include <typeindex>

#include <eventbus/event_bus.hpp>

const char new_line = '\n';

struct dummy_event
struct first_event
{
std::string message;
};

struct other_event
struct second_event
{
int id;
std::string message;
Expand All @@ -21,7 +20,7 @@ struct third_event
double value{ 234.00 };
};

void foo(const dummy_event& evt)
void foo(const first_event& evt)
{
std::cout << "event: " << evt.message << std::endl;
}
Expand All @@ -30,7 +29,7 @@ class my_callback_object
{
public:
my_callback_object() = default;
void on_event_fired(const dummy_event&) { event_count_++; }
void on_event_fired(const first_event&) { event_count_++; }
void on_third_event() {};
[[nodiscard]] int get_event_count() const { return event_count_; }
private:
Expand All @@ -49,33 +48,33 @@ int main()
event_bus evt_bus;
my_callback_object callback_obj;

const auto reg = evt_bus.register_handler<dummy_event>(&foo);
const auto reg = evt_bus.register_handler<first_event>(&foo);
const auto third_event_reg = evt_bus.register_handler<third_event>([](const third_event& evt)
{
std::cout << "my third event handler: " << evt.value << new_line;
});

const auto empty_event_handler = evt_bus.register_handler<third_event>([]() {std::cout << "I just do stuff when a third_event is fired." << new_line; });

dummy_event evt{ "hello from dummy event" };
first_event evt{ "hello from dummy event" };
evt_bus.fire_event(&evt);
evt_bus.fire_event(third_event{ 13.0 });
evt_bus.remove_handler(third_event_reg);
evt_bus.fire_event(third_event{ 13.0 });


const auto other_event_reg = evt_bus.register_handler<other_event>([](const other_event& other_evt) {std::cout << "first other event handler says: " << other_evt.message << std::endl; });
const auto other_event_second_reg = evt_bus.register_handler<other_event>([](const other_event& other_evt){std::cout << "second other event handler says: " << other_evt.id << " " << other_evt.message << std::endl;});
const auto dmy_evt_first_reg = evt_bus.register_handler<dummy_event>([](const dummy_event& dmy_evt) {std::cout << "third event handler says: " << dmy_evt.message << std::endl;});
const auto dmy_evt_pmr_reg = evt_bus.register_handler<dummy_event>(&callback_obj , &my_callback_object::on_event_fired);
const auto other_event_reg = evt_bus.register_handler<second_event>([](const second_event& other_evt) {std::cout << "first other event handler says: " << other_evt.message << std::endl; });
const auto other_event_second_reg = evt_bus.register_handler<second_event>([](const second_event& other_evt){std::cout << "second other event handler says: " << other_evt.id << " " << other_evt.message << std::endl;});
const auto dmy_evt_first_reg = evt_bus.register_handler<first_event>([](const first_event& dmy_evt) {std::cout << "third event handler says: " << dmy_evt.message << std::endl;});
const auto dmy_evt_pmr_reg = evt_bus.register_handler<first_event>(&callback_obj , &my_callback_object::on_event_fired);
const auto thrid_event_reg_pmr = evt_bus.register_handler<third_event>(&callback_obj, &my_callback_object::on_third_event);

// the following does not compile
// third_event_object teo;
// const auto rg = evt_bus.register_handler<third_event>(&teo, &my_callback_object::on_third_event);

other_event other_evt{ 2, "hello there" };
dummy_event dmy_event{ "oh boy..." };
second_event other_evt{ 2, "hello there" };
first_event dmy_event{ "oh boy..." };

evt_bus.fire_event(dmy_event);

Expand Down
Loading

0 comments on commit 5418996

Please sign in to comment.