ModernCPlusPlusDemo
载入中...
搜索中...
未找到
EventBus.hpp
浏览该文件的文档.
1#pragma once
2
3#include <functional>
4#include <unordered_map>
5#include <vector>
6#include <typeindex>
7#include <memory>
8#include <mutex>
9#include <shared_mutex>
10#include <type_traits>
11#include <exception>
12#include <iostream>
13
14template<typename EventBaseType>
16{
17public:
18 // Unique identifier for each subscription
19 using SubscriptionId = size_t;
20
21 // Template function to subscribe to an event type
22 template<typename EventType, typename Callback>
23 SubscriptionId subscribe(Callback&& callback)
24 {
25 static_assert(std::is_base_of_v<EventBaseType, EventType>,
26 "EventType must inherit from EventBaseType");
27 static_assert(std::is_invocable_r_v<void, Callback, const EventType&>,
28 "Callback must be invocable with const EventType&");
29
30 std::unique_lock lock(mutex_);
31 auto& subscribers = subscribers_[std::type_index(typeid(EventType))];
33 subscribers.emplace_back(Subscriber{
34 id,
35 [cb = std::forward<Callback>(callback)](const EventBaseType* event)
36 {
37 try
38 {
39 cb(*static_cast<const EventType*>(event));
40 }
41 catch (const std::exception& e)
42 {
43 std::cerr << "Exception in event callback: " << e.what() << std::endl;
44 }
45 catch (...)
46 {
47 std::cerr << "Unknown exception in event callback" << std::endl;
48 }
49 }
50 });
51 return id;
52 }
53
54 // Function to publish an event
55 template<typename EventType>
56 void publish(const EventType& event) const
57 {
58 static_assert(std::is_base_of_v<EventBaseType, EventType>,
59 "EventType must inherit from EventBaseType");
60
61 std::shared_lock lock(mutex_);
62 if (auto it = subscribers_.find(std::type_index(typeid(EventType))); it != subscribers_.end())
63 {
64 // Create a copy of subscribers to allow for safe iteration
65 auto subscribersCopy = it->second;
66 lock.unlock(); // Release the lock before calling callbacks
67
68 for (const auto& subscriber : subscribersCopy)
69 {
70 subscriber.callback(&event);
71 }
72 }
73 }
74
75 // Function to unsubscribe all callbacks for a specific event type
76 template<typename EventType>
78 {
79 static_assert(std::is_base_of_v<EventBaseType, EventType>,
80 "EventType must inherit from EventBaseType");
81
82 std::unique_lock lock(mutex_);
83 subscribers_.erase(std::type_index(typeid(EventType)));
84 }
85
86 // Function to unsubscribe a specific subscription
88 {
89 std::unique_lock lock(mutex_);
90 for (auto& [_, subscribers] : subscribers_)
91 {
92 subscribers.erase(
93 std::remove_if(subscribers.begin(), subscribers.end(),
94 [id](const auto& subscriber) { return subscriber.id == id; }),
95 subscribers.end()
96 );
97 }
98 }
99
100private:
101 // Structure to hold subscriber information
103 {
105 std::function<void(const EventBaseType*)> callback;
106 };
107
108 using SubscriberList = std::vector<Subscriber>;
109
110 mutable std::shared_mutex mutex_; // Mutex for thread-safety
111 std::unordered_map<std::type_index, SubscriberList> subscribers_; // Map of event types to subscribers
112 SubscriptionId nextSubscriptionId_ = 0; // Counter for generating unique subscription IDs
113};
114
115//=============================================Usage example===================================================
116
117// struct Event { virtual ~Event() = default; };
118// struct UserCreatedEvent : Event { std::string username; };
119
120// int main()
121// {
122// EventBus<Event> bus;
123
124// auto id1 = bus.subscribe<UserCreatedEvent>([](const UserCreatedEvent& e) {
125// std::cout << "User created: " << e.username << std::endl;
126// });
127
128// auto id2 = bus.subscribe<UserCreatedEvent>([](const UserCreatedEvent& e) {
129// throw std::runtime_error("Test exception");
130// });
131
132// bus.publish(UserCreatedEvent{"John"}); // This will print "User created: John" and an exception message
133
134// bus.unsubscribe(id2); // Unsubscribe the throwing callback
135
136// bus.publish(UserCreatedEvent{"Jane"}); // This will only print "User created: Jane"
137
138// bus.unsubscribeAll<UserCreatedEvent>(); // Unsubscribe all UserCreatedEvent callbacks
139
140// bus.publish(UserCreatedEvent{"Bob"}); // This won't print anything
141
142// return 0;
143// }
Definition EventBus.hpp:16
void publish(const EventType &event) const
Definition EventBus.hpp:56
std::shared_mutex mutex_
Definition EventBus.hpp:110
SubscriptionId nextSubscriptionId_
Definition EventBus.hpp:112
std::unordered_map< std::type_index, SubscriberList > subscribers_
Definition EventBus.hpp:111
size_t SubscriptionId
Definition EventBus.hpp:19
std::vector< Subscriber > SubscriberList
Definition EventBus.hpp:108
void unsubscribe(SubscriptionId id)
Definition EventBus.hpp:87
void unsubscribeAll()
Definition EventBus.hpp:77
SubscriptionId subscribe(Callback &&callback)
Definition EventBus.hpp:23
Definition EventBus.hpp:103
std::function< void(const EventBaseType *)> callback
Definition EventBus.hpp:105
SubscriptionId id
Definition EventBus.hpp:104