Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use subscription based events handling #237

Open
wants to merge 27 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
37e0a8c
Used a lambda based events
Mar 1, 2024
9349d97
Merge branch 'dev' into events
markaren Mar 1, 2024
4797df2
Create individual dispatcher for each event
Mar 1, 2024
2b906e4
Add mouse support and refactor.
Mar 1, 2024
0162d1c
fix broken scroll wheel for orbit control
Mar 1, 2024
f0df38e
shorten the event handling util names
Mar 1, 2024
095fbaf
Merge branch 'dev' into events
markaren Mar 2, 2024
897a009
implement ioCapture
markaren Mar 3, 2024
44a76b1
implement keys for Youbot
markaren Mar 3, 2024
44cb476
Fix for instancing crash
markaren Mar 3, 2024
b64cae4
missing conversions
markaren Mar 3, 2024
769a744
missing conversions
markaren Mar 3, 2024
927534b
#239 Fix UB in event dispatching
Mar 4, 2024
03675b2
Merge branch 'events' of github.com:bradphelan/threepp into events
Mar 4, 2024
aca27f9
#239 Fix UB in event dispatching
Mar 4, 2024
66ef3ee
Merge branch 'dev' into events
markaren Mar 4, 2024
3c8baca
Merge branch 'dev' into events
markaren Mar 4, 2024
764f47d
Merge branch 'dev' into events
markaren Mar 5, 2024
f606bc0
Merge branch 'dev' into events
markaren Mar 14, 2024
eb198be
update new code
markaren Mar 14, 2024
9c447c8
formatting and refactor
markaren Mar 14, 2024
014b9cc
Merge branch 'dev' into events
markaren Mar 19, 2024
5755cf9
adapt new code
markaren Mar 19, 2024
e569f77
Merge branch 'dev' into events
markaren Mar 23, 2024
a9c25db
adapt new code
markaren Mar 23, 2024
f6338b1
Merge branch 'dev' into events
markaren Mar 24, 2024
8acd6ff
Adapt DragControls
markaren Mar 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 38 additions & 15 deletions include/threepp/core/EventDispatcher.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#include <vector>
#include <functional>
#include <algorithm>
#include <atomic>
#include <threepp/utils/Scope.hpp>
bradphelan marked this conversation as resolved.
Show resolved Hide resolved


namespace threepp {
Expand All @@ -29,7 +29,7 @@ namespace threepp {
using TEventListener = std::function<void(TEvent&)>;

/// A single subscription for an event
using Subscription = std::shared_ptr<void>;
using Subscription = threepp::utils::ScopeExit;

/// For holding a large number of subscriptions to events
using Subscriptions= std::vector<Subscription>;
Expand All @@ -43,28 +43,34 @@ namespace threepp {
/// Generic event dispatch class
template <typename TEvent>
#if defined(__cpp_concepts) && (__cpp_concepts >= 201907L)
// C++20 (and later) code
requires concepts::Event<TEvent>
#endif
// C++20 (and later) code
class TEventDispatcher {
private:
void unsubscribe(size_t id) {
if (!sending_)
listeners_.erase(id);
else
to_unsubscribe_.push_back(id);
}
public:
using EventListener = TEventListener<TEvent>;

/// Adds an event listener and returns a subscription
[[nodiscard]] Subscription subscribe(EventListener listener) {
size_t current_id = id_.load();
listeners_.insert({ current_id, listener });
Subscription disposer((void*) nullptr, [this, current_id](void*) { listeners_.erase(current_id); });
id_ = id_ + 1;
return disposer;
size_t current_id = id_;
id_++;
listeners_.insert({current_id, listener});
return utils::at_scope_exit([this, current_id]() { unsubscribe(current_id); });
}

/// Adds an event listener and never automatically unsubscribes. You
/// can set event.unsubscribe = true and the subscription will be
/// cancelled. Not recommended to be used directly. Build other
/// tools on this.
void subscribeForever(EventListener listener) {
markaren marked this conversation as resolved.
Show resolved Hide resolved
size_t current_id = id_.load();
size_t current_id = id_;
listeners_.insert({ current_id, listener });
id_ = id_ + 1;
}
Expand All @@ -85,16 +91,28 @@ namespace threepp {

/// Send an event to all listeners.
void send(TEvent & e){
std::vector<size_t> toUnsubscribe;
for (auto const& item : listeners_) {
item.second(e);
/// Mark that we are in the sending state.
auto tmp = utils::reset_at_scope_exit(sending_, true);

for(auto it = listeners_.begin(); it != listeners_.end();)
{
it->second(e);
if (e.unsubscribe) {
e.unsubscribe = false;
toUnsubscribe.push_back(item.first);
it = listeners_.erase(it);
}
else
it++;
}
for (size_t id : toUnsubscribe)

// Unsubscribe listeners that disposed of their
// subscription by calling unsubscribe directly
// during the event sending phase above.
for(size_t id : to_unsubscribe_)
listeners_.erase(id);

if (to_unsubscribe_.size() > 0)
to_unsubscribe_.clear();
}

/// Handle r-value versions of send
Expand All @@ -106,7 +124,12 @@ namespace threepp {

private:
std::unordered_map<size_t, EventListener> listeners_;
std::atomic<size_t> id_ = 0;
/// The id of the current listener
size_t id_ = 0;
/// Are we sending event? Used to detect unsubscriptions during sending.
bool sending_ = false;
/// Subscriptions to be delay unsubscribed.
std::vector<size_t> to_unsubscribe_;
};


Expand Down
6 changes: 5 additions & 1 deletion tests/core/EventDispatcher_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ TEST_CASE("Test subscribe") {
evt.send(Event{});
REQUIRE(nCalls == 2);
}
evt.send(Event{});
evt.send(Event{});
REQUIRE(nCalls == 2);

}
Expand Down Expand Up @@ -55,3 +55,7 @@ TEST_CASE("Test subscribeOnce") {
evt.send(Event{});
REQUIRE(nCalls == 1);
}

TEST_CASE("Unsubscribe due to message") {

}
2 changes: 2 additions & 0 deletions tests/utils/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@

add_test_executable(StringUtils_test)
add_test_executable(ScopeUtils_test)