Skip to content

Conversation

@DavidWang19
Copy link

No description provided.

@DavidWang19 DavidWang19 force-pushed the master branch 3 times, most recently from 2ba258b to e1fe884 Compare November 3, 2025 05:37
@MistEO MistEO requested a review from Copilot November 5, 2025 09:35
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces a static event bus system for the MaaUtils library with support for priority-based event handling, cancellable events, and weak pointer lifecycle management. The implementation provides both free function and member function subscription mechanisms.

  • Adds StaticEventBus.h header with event bus implementation using templates and concepts
  • Implements StaticEventBus.cpp for registry management
  • Includes comprehensive test suite covering basic subscriptions, priority ordering, weak pointer cleanup, and cancellable events

Reviewed Changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
include/MaaUtils/StaticEventBus.h Core event bus implementation with Event/CancellableEvent classes, EventStorage registry, and StaticEventManager API
source/StaticEventBus/StaticEventBus.cpp Provides global EventStorageRegistry singleton implementation
test/StaticEventBusTest.cpp Comprehensive test suite with 6 test cases covering all major features
test/CMakeLists.txt CMake configuration for building the test executable
.gitignore Comments out VS Code settings.json from ignore list

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

callback(event);
}
else {
static_assert(false, "Callback must be invocable with EventT& or const EventT&");
Copy link

Copilot AI Nov 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using static_assert(false, ...) is ill-formed in C++. It will always fail even when not instantiated. Use a type-dependent expression like static_assert(sizeof(Callable) == 0, ...) or static_assert(!sizeof(Callable*), ...) to ensure it only fires when the template is actually instantiated with an invalid type.

Suggested change
static_assert(false, "Callback must be invocable with EventT& or const EventT&");
static_assert(
!std::is_invocable_v<Callable&, EventT&> &&
!std::is_invocable_v<Callable&, const EventT&>,
"Callback must be invocable with EventT& or const EventT&"
);

Copilot uses AI. Check for mistakes.
(shared_owner.get()->*callback)(event);
}
else {
static_assert(false, "Callback must be invocable with EventT& or const EventT&");
Copy link

Copilot AI Nov 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using static_assert(false, ...) is ill-formed in C++. It will always fail even when not instantiated. Use a type-dependent expression like static_assert(sizeof(Callable) == 0, ...) or static_assert(!sizeof(Callable*), ...) to ensure it only fires when the template is actually instantiated with an invalid type.

Suggested change
static_assert(false, "Callback must be invocable with EventT& or const EventT&");
static_assert(sizeof(Callable) == 0, "Callback must be invocable with EventT& or const EventT&");

Copilot uses AI. Check for mistakes.
Comment on lines +69 to +82
EventStorage<EventT>& get_storage()
{
std::type_index type_idx(typeid(EventT));
auto it = storages_.find(type_idx);
if (it == storages_.end()) {
auto storage = std::make_unique<EventStorage<EventT>>();
auto* storage_ptr = storage.get();
storages_[type_idx] = std::move(storage);
return *storage_ptr;
}
else {
return *static_cast<EventStorage<EventT>*>(it->second.get());
}
}
Copy link

Copilot AI Nov 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The get_storage() method modifies storages_ without synchronization. If multiple threads call subscribe() or publish() concurrently with different event types, this can lead to race conditions during map modification. Consider adding mutex protection around storages_ access.

Copilot uses AI. Check for mistakes.
Comment on lines +116 to +121
storage.subscriptions.insert(
std::lower_bound(
storage.subscriptions.begin(),
storage.subscriptions.end(),
typename EventStorage<EventT>::Subscription { priority, false, {}, {} }),
{ priority, false, std::move(wrapper), {} });
Copy link

Copilot AI Nov 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The subscribe() method modifies storage.subscriptions without synchronization. Concurrent calls to subscribe() or simultaneous publish() operations on the same event type can cause data races. Consider adding mutex protection for subscription vector modifications.

Copilot uses AI. Check for mistakes.
Comment on lines +162 to +176
for (const auto& subscription : storage.subscriptions) {
if (subscription.has_owner && subscription.owner.expired()) {
need_erase = true;
continue;
}
subscription.callback(event);
if constexpr (std::derived_from<EventT, CancellableEvent>) {
if (event.is_cancelled()) {
break;
}
}
}
if (need_erase) {
std::erase_if(storage.subscriptions, [](const auto& sub) { return sub.has_owner && sub.owner.expired(); });
}
Copy link

Copilot AI Nov 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The publish() method iterates over and potentially modifies storage.subscriptions without synchronization. If another thread calls subscribe() during publication, this creates a data race. The iteration and cleanup operations need to be protected with the same mutex used in subscribe().

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant