Common System 0.2.0
Common interfaces and patterns for system integration
Loading...
Searching...
No Matches
patterns.cppm
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2025, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
15module;
16
17#include <algorithm>
18#include <atomic>
19#include <chrono>
20#include <cstdint>
21#include <functional>
22#include <memory>
23#include <mutex>
24#include <shared_mutex>
25#include <typeindex>
26#include <typeinfo>
27#include <unordered_map>
28#include <vector>
29
30export module kcenon.common:patterns;
31
32export namespace kcenon::common::patterns {
33
34// ============================================================================
35// Event Bus
36// ============================================================================
37
46public:
48
50 stop();
51 }
52
56 void start() {
57 running_.store(true, std::memory_order_release);
58 }
59
63 void stop() {
64 running_.store(false, std::memory_order_release);
65 }
66
70 bool is_running() const {
71 return running_.load(std::memory_order_acquire);
72 }
73
80 template<typename Event>
81 uint64_t subscribe(std::function<void(const Event&)> handler) {
82 std::unique_lock lock(mutex_);
83 uint64_t id = next_id_++;
84 auto type = std::type_index(typeid(Event));
85
86 auto& handlers = handlers_[type];
87 handlers.push_back({id, [handler](const void* event) {
88 handler(*static_cast<const Event*>(event));
89 }});
90
91 return id;
92 }
93
99 std::unique_lock lock(mutex_);
100 for (auto& [type, handlers] : handlers_) {
101 handlers.erase(
102 std::remove_if(handlers.begin(), handlers.end(),
103 [subscription_id](const auto& entry) {
104 return entry.id == subscription_id;
105 }),
106 handlers.end());
107 }
108 }
109
115 template<typename Event>
116 void publish(const Event& event) {
117 if (!is_running()) return;
118
119 std::shared_lock lock(mutex_);
120 auto type = std::type_index(typeid(Event));
121 auto it = handlers_.find(type);
122 if (it != handlers_.end()) {
123 for (const auto& entry : it->second) {
124 entry.handler(&event);
125 }
126 }
127 }
128
132 template<typename Event>
133 size_t subscriber_count() const {
134 std::shared_lock lock(mutex_);
135 auto type = std::type_index(typeid(Event));
136 auto it = handlers_.find(type);
137 if (it != handlers_.end()) {
138 return it->second.size();
139 }
140 return 0;
141 }
142
146 void clear() {
147 std::unique_lock lock(mutex_);
148 handlers_.clear();
149 }
150
151private:
153 uint64_t id;
154 std::function<void(const void*)> handler;
155 };
156
157 mutable std::shared_mutex mutex_;
158 std::atomic<bool> running_;
159 std::atomic<uint64_t> next_id_;
160 std::unordered_map<std::type_index, std::vector<HandlerEntry>> handlers_;
161};
162
163// ============================================================================
164// Result Helpers (re-exported from result partition)
165// ============================================================================
166
167// Note: Result<T> and related types are in the :result partition
168// This partition focuses on design patterns like EventBus
169
170} // namespace kcenon::common::patterns
Thread-safe event bus for publish/subscribe pattern.
Definition patterns.cppm:45
bool is_running() const
Check if the event bus is running.
Definition patterns.cppm:70
void publish(const Event &event)
Publish an event to all subscribers.
void start()
Start the event bus.
Definition patterns.cppm:56
void clear()
Clear all subscriptions.
std::unordered_map< std::type_index, std::vector< HandlerEntry > > handlers_
size_t subscriber_count() const
Get the number of subscribers for an event type.
uint64_t subscribe(std::function< void(const Event &)> handler)
Subscribe to events of a specific type.
Definition patterns.cppm:81
void unsubscribe(uint64_t subscription_id)
Unsubscribe from events.
Definition patterns.cppm:98
uint64_t subscription_id
Type alias for subscription ID.
Definition event_bus.h:105
Generic event structure for the event bus.
Definition event_bus.h:111