|
| 1 | +# Generic Event Handling System |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +The Generic Event Handling System provides a type-safe, flexible, and thread-safe mechanism for handling events in C++. It supports both observer patterns and callback-based event handling, making it suitable for various use cases in native API development. |
| 6 | + |
| 7 | +## Key Features |
| 8 | + |
| 9 | +- **Type Safety**: Template-based design ensures compile-time type checking |
| 10 | +- **Flexible Patterns**: Supports both observer pattern and callback-based handling |
| 11 | +- **Thread Safety**: Safe for multi-threaded environments with proper synchronization |
| 12 | +- **Asynchronous Processing**: Built-in support for async event dispatch with background thread |
| 13 | +- **Automatic Cleanup**: RAII-based listener management prevents memory leaks |
| 14 | +- **Exception Safety**: Handles exceptions in event listeners gracefully |
| 15 | +- **Event Timestamping**: All events include creation timestamps |
| 16 | +- **Generic Design**: Works with any event type through templates |
| 17 | + |
| 18 | +## Core Components |
| 19 | + |
| 20 | +### Event Base Classes |
| 21 | + |
| 22 | +- `Event`: Base class for all events, provides timestamping and type information |
| 23 | +- `TypedEvent<T>`: Template base class that provides automatic type identification |
| 24 | +- `EventListener`: Generic event listener interface |
| 25 | +- `TypedEventListener<T>`: Type-safe event listener for specific event types |
| 26 | +- `CallbackEventListener<T>`: Wrapper for std::function callbacks |
| 27 | + |
| 28 | +### Event Dispatcher |
| 29 | + |
| 30 | +- `EventDispatcher`: Main class that manages event distribution |
| 31 | +- Supports both synchronous and asynchronous event dispatch |
| 32 | +- Thread-safe listener management |
| 33 | +- Background thread for async event processing |
| 34 | + |
| 35 | +### Utility Classes |
| 36 | + |
| 37 | +- `EventListenerGuard`: RAII helper for automatic listener cleanup |
| 38 | +- `GetGlobalEventDispatcher()`: Singleton access to global event dispatcher |
| 39 | + |
| 40 | +## Usage Examples |
| 41 | + |
| 42 | +### 1. Define Custom Events |
| 43 | + |
| 44 | +```cpp |
| 45 | +#include "event_system.h" |
| 46 | + |
| 47 | +// Define a custom event |
| 48 | +class UserLoginEvent : public nativeapi::TypedEvent<UserLoginEvent> { |
| 49 | + public: |
| 50 | + UserLoginEvent(const std::string& username, bool success) |
| 51 | + : username_(username), success_(success) {} |
| 52 | + |
| 53 | + const std::string& GetUsername() const { return username_; } |
| 54 | + bool IsSuccess() const { return success_; } |
| 55 | + |
| 56 | + private: |
| 57 | + std::string username_; |
| 58 | + bool success_; |
| 59 | +}; |
| 60 | +``` |
| 61 | +
|
| 62 | +### 2. Observer Pattern |
| 63 | +
|
| 64 | +```cpp |
| 65 | +// Implement an observer |
| 66 | +class LoginObserver : public nativeapi::TypedEventListener<UserLoginEvent> { |
| 67 | + public: |
| 68 | + void OnTypedEvent(const UserLoginEvent& event) override { |
| 69 | + std::cout << "User " << event.GetUsername() |
| 70 | + << (event.IsSuccess() ? " logged in" : " login failed") << std::endl; |
| 71 | + } |
| 72 | +}; |
| 73 | +
|
| 74 | +// Register the observer |
| 75 | +nativeapi::EventDispatcher dispatcher; |
| 76 | +LoginObserver observer; |
| 77 | +auto listener_id = dispatcher.AddListener<UserLoginEvent>(&observer); |
| 78 | +
|
| 79 | +// Dispatch an event |
| 80 | +dispatcher.DispatchSync<UserLoginEvent>("john_doe", true); |
| 81 | +
|
| 82 | +// Clean up |
| 83 | +dispatcher.RemoveListener(listener_id); |
| 84 | +``` |
| 85 | + |
| 86 | +### 3. Callback Pattern |
| 87 | + |
| 88 | +```cpp |
| 89 | +// Register a callback function |
| 90 | +auto callback_id = dispatcher.AddListener<UserLoginEvent>( |
| 91 | + [](const UserLoginEvent& event) { |
| 92 | + // Handle the event |
| 93 | + std::cout << "Callback: " << event.GetUsername() << std::endl; |
| 94 | + }); |
| 95 | + |
| 96 | +// Or use RAII for automatic cleanup |
| 97 | +auto guard = nativeapi::AddScopedListener<UserLoginEvent>(dispatcher, |
| 98 | + [](const UserLoginEvent& event) { |
| 99 | + std::cout << "Scoped callback: " << event.GetUsername() << std::endl; |
| 100 | + }); |
| 101 | +// Listener is automatically removed when guard goes out of scope |
| 102 | +``` |
| 103 | +
|
| 104 | +### 4. Multi-Event Observer |
| 105 | +
|
| 106 | +```cpp |
| 107 | +// Handle multiple event types with one observer |
| 108 | +class MultiEventObserver : public nativeapi::EventListener { |
| 109 | + public: |
| 110 | + void OnEvent(const nativeapi::Event& event) override { |
| 111 | + if (auto login_event = dynamic_cast<const UserLoginEvent*>(&event)) { |
| 112 | + HandleLogin(*login_event); |
| 113 | + } else if (auto logout_event = dynamic_cast<const UserLogoutEvent*>(&event)) { |
| 114 | + HandleLogout(*logout_event); |
| 115 | + } |
| 116 | + } |
| 117 | + |
| 118 | + private: |
| 119 | + void HandleLogin(const UserLoginEvent& event) { /* ... */ } |
| 120 | + void HandleLogout(const UserLogoutEvent& event) { /* ... */ } |
| 121 | +}; |
| 122 | +``` |
| 123 | + |
| 124 | +### 5. Asynchronous Event Processing |
| 125 | + |
| 126 | +```cpp |
| 127 | +// Start background thread for async processing |
| 128 | +dispatcher.Start(); |
| 129 | + |
| 130 | +// Dispatch events asynchronously |
| 131 | +dispatcher.DispatchAsync<UserLoginEvent>("alice", true); |
| 132 | +dispatcher.DispatchAsync<UserLoginEvent>("bob", false); |
| 133 | + |
| 134 | +// Events will be processed on background thread |
| 135 | +// Stop background processing when done |
| 136 | +dispatcher.Stop(); |
| 137 | +``` |
| 138 | + |
| 139 | +### 6. Global Event System |
| 140 | + |
| 141 | +```cpp |
| 142 | +// Use the global event dispatcher |
| 143 | +auto& global_dispatcher = nativeapi::GetGlobalEventDispatcher(); |
| 144 | + |
| 145 | +global_dispatcher.AddListener<UserLoginEvent>([](const UserLoginEvent& event) { |
| 146 | + // This listener is globally available |
| 147 | +}); |
| 148 | +``` |
| 149 | + |
| 150 | +## Thread Safety |
| 151 | + |
| 152 | +The event system is designed to be thread-safe: |
| 153 | + |
| 154 | +- Listener registration/removal is protected by mutexes |
| 155 | +- Event dispatch creates snapshots of listeners to avoid holding locks during dispatch |
| 156 | +- Async event processing uses condition variables for efficient waiting |
| 157 | +- Exception handling prevents one listener from affecting others |
| 158 | + |
| 159 | +## Performance Considerations |
| 160 | + |
| 161 | +- **Synchronous dispatch**: Direct function calls, minimal overhead |
| 162 | +- **Asynchronous dispatch**: Events are queued and processed on background thread |
| 163 | +- **Memory management**: Automatic cleanup of callback listeners |
| 164 | +- **Exception handling**: Try-catch blocks around listener calls |
| 165 | + |
| 166 | +## Integration with Existing Code |
| 167 | + |
| 168 | +The event system can be integrated with existing components: |
| 169 | + |
| 170 | +```cpp |
| 171 | +// Example: Extend DisplayManager to use events |
| 172 | +class EventAwareDisplayManager : public DisplayManager { |
| 173 | + public: |
| 174 | + EventAwareDisplayManager(nativeapi::EventDispatcher& dispatcher) |
| 175 | + : dispatcher_(dispatcher) {} |
| 176 | + |
| 177 | + protected: |
| 178 | + void OnDisplayAdded(const Display& display) { |
| 179 | + // Existing logic... |
| 180 | + |
| 181 | + // Dispatch event |
| 182 | + dispatcher_.DispatchAsync<nativeapi::DisplayAddedEvent>(display); |
| 183 | + } |
| 184 | + |
| 185 | + private: |
| 186 | + nativeapi::EventDispatcher& dispatcher_; |
| 187 | +}; |
| 188 | +``` |
| 189 | +
|
| 190 | +## Best Practices |
| 191 | +
|
| 192 | +1. **Use RAII**: Prefer `EventListenerGuard` or scoped listeners for automatic cleanup |
| 193 | +2. **Handle exceptions**: Event listeners should handle their own exceptions |
| 194 | +3. **Avoid blocking**: Keep event handlers fast to avoid blocking other listeners |
| 195 | +4. **Use appropriate dispatch**: Sync for immediate handling, async for background processing |
| 196 | +5. **Clean up**: Remove listeners when they're no longer needed |
| 197 | +6. **Type safety**: Prefer `TypedEventListener` over raw `EventListener` when possible |
| 198 | +
|
| 199 | +## Common Event Types |
| 200 | +
|
| 201 | +The system includes predefined events for common scenarios: |
| 202 | +
|
| 203 | +- `DisplayAddedEvent`, `DisplayRemovedEvent`: Display management |
| 204 | +- `KeyPressedEvent`, `KeyReleasedEvent`: Keyboard input |
| 205 | +- `MouseMovedEvent`, `MouseClickedEvent`: Mouse input |
| 206 | +- `WindowCreatedEvent`, `WindowClosedEvent`: Window management |
| 207 | +- `ApplicationStartedEvent`, `ApplicationExitingEvent`: Application lifecycle |
| 208 | +
|
| 209 | +These can be used directly or serve as examples for creating custom events. |
0 commit comments