diff --git a/include/core/event/event_bus_macros.h b/include/core/event/event_bus_macros.h deleted file mode 100644 index a067be3..0000000 --- a/include/core/event/event_bus_macros.h +++ /dev/null @@ -1,112 +0,0 @@ -#pragma once - -#include - -#define E2D_EVENT_BUS_NAME_(n) n##_Bus - -/** - * @brief 声明事件总线 - */ -#define DECLARE_EVENT_BUS(BusName) \ - struct BusName##_Bus { \ - static constexpr const char* NAME = #BusName; \ - }; - -/** - * @brief 声明无参数事件 - */ -#define DECLARE_EVENT_0(EventName, BusName) \ - struct EventName : ::extra2d::event::EventTrait { \ - using Listener = ::extra2d::event::Listener; \ - static constexpr const char* NAME = #EventName; \ - static constexpr const char* BUS_NAME = E2D_EVENT_BUS_NAME_(BusName)::NAME; \ - static void emit() { ::extra2d::event::broadcast(); } \ - }; - -/** - * @brief 声明单参数事件 - */ -#define DECLARE_EVENT_1(EventName, BusName, Arg0) \ - struct EventName : ::extra2d::event::EventTrait { \ - using Listener = ::extra2d::event::Listener; \ - static constexpr const char* NAME = #EventName; \ - static constexpr const char* BUS_NAME = E2D_EVENT_BUS_NAME_(BusName)::NAME; \ - static void emit(Arg0 arg0) { ::extra2d::event::broadcast(arg0); } \ - }; - -/** - * @brief 声明双参数事件 - */ -#define DECLARE_EVENT_2(EventName, BusName, Arg0, Arg1) \ - struct EventName : ::extra2d::event::EventTrait { \ - using Listener = ::extra2d::event::Listener; \ - static constexpr const char* NAME = #EventName; \ - static constexpr const char* BUS_NAME = E2D_EVENT_BUS_NAME_(BusName)::NAME; \ - static void emit(Arg0 arg0, Arg1 arg1) { ::extra2d::event::broadcast(arg0, arg1); } \ - }; - -/** - * @brief 声明三参数事件 - */ -#define DECLARE_EVENT_3(EventName, BusName, Arg0, Arg1, Arg2) \ - struct EventName : ::extra2d::event::EventTrait { \ - using Listener = ::extra2d::event::Listener; \ - static constexpr const char* NAME = #EventName; \ - static constexpr const char* BUS_NAME = E2D_EVENT_BUS_NAME_(BusName)::NAME; \ - static void emit(Arg0 arg0, Arg1 arg1, Arg2 arg2) { ::extra2d::event::broadcast(arg0, arg1, arg2); } \ - }; - -/** - * @brief 声明四参数事件 - */ -#define DECLARE_EVENT_4(EventName, BusName, Arg0, Arg1, Arg2, Arg3) \ - struct EventName : ::extra2d::event::EventTrait { \ - using Listener = ::extra2d::event::Listener; \ - static constexpr const char* NAME = #EventName; \ - static constexpr const char* BUS_NAME = E2D_EVENT_BUS_NAME_(BusName)::NAME; \ - static void emit(Arg0 arg0, Arg1 arg1, Arg2 arg2, Arg3 arg3) { ::extra2d::event::broadcast(arg0, arg1, arg2, arg3); } \ - }; - -/** - * @brief 声明五参数事件 - */ -#define DECLARE_EVENT_5(EventName, BusName, Arg0, Arg1, Arg2, Arg3, Arg4) \ - struct EventName : ::extra2d::event::EventTrait { \ - using Listener = ::extra2d::event::Listener; \ - static constexpr const char* NAME = #EventName; \ - static constexpr const char* BUS_NAME = E2D_EVENT_BUS_NAME_(BusName)::NAME; \ - static void emit(Arg0 arg0, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) { ::extra2d::event::broadcast(arg0, arg1, arg2, arg3, arg4); } \ - }; - -/** - * @brief 声明六参数事件 - */ -#define DECLARE_EVENT_6(EventName, BusName, Arg0, Arg1, Arg2, Arg3, Arg4, Arg5) \ - struct EventName : ::extra2d::event::EventTrait { \ - using Listener = ::extra2d::event::Listener; \ - static constexpr const char* NAME = #EventName; \ - static constexpr const char* BUS_NAME = E2D_EVENT_BUS_NAME_(BusName)::NAME; \ - static void emit(Arg0 arg0, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5) { ::extra2d::event::broadcast(arg0, arg1, arg2, arg3, arg4, arg5); } \ - }; - -/** - * @brief 声明七参数事件 - */ -#define DECLARE_EVENT_7(EventName, BusName, Arg0, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6) \ - struct EventName : ::extra2d::event::EventTrait { \ - using Listener = ::extra2d::event::Listener; \ - static constexpr const char* NAME = #EventName; \ - static constexpr const char* BUS_NAME = E2D_EVENT_BUS_NAME_(BusName)::NAME; \ - static void emit(Arg0 arg0, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5, Arg6 arg6) { ::extra2d::event::broadcast(arg0, arg1, arg2, arg3, arg4, arg5, arg6); } \ - }; - -/** - * @brief 声明八参数事件 - */ -#define DECLARE_EVENT_8(EventName, BusName, Arg0, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7) \ - struct EventName : ::extra2d::event::EventTrait { \ - using Listener = ::extra2d::event::Listener; \ - static constexpr const char* NAME = #EventName; \ - static constexpr const char* BUS_NAME = E2D_EVENT_BUS_NAME_(BusName)::NAME; \ - static void emit(Arg0 arg0, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5, Arg6 arg6, Arg7 arg7) { ::extra2d::event::broadcast(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); } \ - }; diff --git a/include/core/scheduler.h b/include/core/scheduler.h index 31d6650..3502e73 100644 --- a/include/core/scheduler.h +++ b/include/core/scheduler.h @@ -4,12 +4,11 @@ #include #include #include -#include -#include -#include -#include #include #include +#include +#include +#include namespace extra2d { @@ -65,7 +64,7 @@ protected: /** * @brief 调度器 * - * 基于 TBB 实现的线程安全调度器,支持定时器和 update 回调 + * 基于标准库实现的线程安全调度器,支持定时器和 update 回调 */ class Scheduler { public: @@ -107,10 +106,27 @@ private: bool operator<(const UpdateEntry& o) const { return pri > o.pri; } }; + // 线程安全的优先队列包装 + class SafePriorityQueue { + public: + void push(const UpdateEntry& entry); + bool pop(UpdateEntry& entry); + bool empty() const; + size_t size() const; + void clear(); + private: + mutable std::mutex mutex_; + std::priority_queue queue_; + }; + std::vector updates_; - tbb::concurrent_hash_map updateIndex_; - tbb::concurrent_hash_map> timers_; - tbb::concurrent_priority_queue updateQueue_; + std::unordered_map updateIndex_; + mutable std::mutex updateIndexMutex_; + + std::unordered_map> timers_; + mutable std::mutex timersMutex_; + + SafePriorityQueue updateQueue_; std::atomic nextHdl_{1}; std::atomic timeScale_{1.0f}; diff --git a/include/core/service.h b/include/core/service.h index 870f547..91cc8dd 100644 --- a/include/core/service.h +++ b/include/core/service.h @@ -6,7 +6,8 @@ #include #include #include -#include +#include +#include namespace extra2d { @@ -88,8 +89,10 @@ public: private: SvcMgr() = default; - using SvcMap = tbb::concurrent_hash_map>; + using SvcMap = std::unordered_map>; SvcMap svcMap_; + mutable std::mutex svcMapMutex_; + std::vector> sortedSvcs_; void sortSvcs(); diff --git a/include/core/event/event_bus.h b/include/event/event_bus.h similarity index 100% rename from include/core/event/event_bus.h rename to include/event/event_bus.h diff --git a/include/event/event_bus_macros.h b/include/event/event_bus_macros.h new file mode 100644 index 0000000..9fc1bed --- /dev/null +++ b/include/event/event_bus_macros.h @@ -0,0 +1,162 @@ +#pragma once + +#include + +#define E2D_EVENT_BUS_NAME_(n) n##_Bus + +/** + * @brief 声明事件总线 + */ +#define DECLARE_EVENT_BUS(BusName) \ + struct BusName##_Bus { \ + static constexpr const char *NAME = #BusName; \ + }; + +/** + * @brief 声明无参数事件 + */ +#define DECLARE_EVENT_0(EventName, BusName) \ + struct EventName \ + : ::extra2d::event::EventTrait { \ + using Listener = ::extra2d::event::Listener; \ + static constexpr const char *NAME = #EventName; \ + static constexpr const char *BUS_NAME = \ + E2D_EVENT_BUS_NAME_(BusName)::NAME; \ + static void emit() { ::extra2d::event::broadcast(); } \ + }; + +/** + * @brief 声明单参数事件 + */ +#define DECLARE_EVENT_1(EventName, BusName, Arg0) \ + struct EventName \ + : ::extra2d::event::EventTrait { \ + using Listener = ::extra2d::event::Listener; \ + static constexpr const char *NAME = #EventName; \ + static constexpr const char *BUS_NAME = \ + E2D_EVENT_BUS_NAME_(BusName)::NAME; \ + static void emit(Arg0 arg0) { \ + ::extra2d::event::broadcast(arg0); \ + } \ + }; + +/** + * @brief 声明双参数事件 + */ +#define DECLARE_EVENT_2(EventName, BusName, Arg0, Arg1) \ + struct EventName \ + : ::extra2d::event::EventTrait { \ + using Listener = ::extra2d::event::Listener; \ + static constexpr const char *NAME = #EventName; \ + static constexpr const char *BUS_NAME = \ + E2D_EVENT_BUS_NAME_(BusName)::NAME; \ + static void emit(Arg0 arg0, Arg1 arg1) { \ + ::extra2d::event::broadcast(arg0, arg1); \ + } \ + }; + +/** + * @brief 声明三参数事件 + */ +#define DECLARE_EVENT_3(EventName, BusName, Arg0, Arg1, Arg2) \ + struct EventName \ + : ::extra2d::event::EventTrait { \ + using Listener = ::extra2d::event::Listener; \ + static constexpr const char *NAME = #EventName; \ + static constexpr const char *BUS_NAME = \ + E2D_EVENT_BUS_NAME_(BusName)::NAME; \ + static void emit(Arg0 arg0, Arg1 arg1, Arg2 arg2) { \ + ::extra2d::event::broadcast(arg0, arg1, arg2); \ + } \ + }; + +/** + * @brief 声明四参数事件 + */ +#define DECLARE_EVENT_4(EventName, BusName, Arg0, Arg1, Arg2, Arg3) \ + struct EventName \ + : ::extra2d::event::EventTrait { \ + using Listener = ::extra2d::event::Listener; \ + static constexpr const char *NAME = #EventName; \ + static constexpr const char *BUS_NAME = \ + E2D_EVENT_BUS_NAME_(BusName)::NAME; \ + static void emit(Arg0 arg0, Arg1 arg1, Arg2 arg2, Arg3 arg3) { \ + ::extra2d::event::broadcast(arg0, arg1, arg2, arg3); \ + } \ + }; + +/** + * @brief 声明五参数事件 + */ +#define DECLARE_EVENT_5(EventName, BusName, Arg0, Arg1, Arg2, Arg3, Arg4) \ + struct EventName \ + : ::extra2d::event::EventTrait { \ + using Listener = ::extra2d::event::Listener; \ + static constexpr const char *NAME = #EventName; \ + static constexpr const char *BUS_NAME = \ + E2D_EVENT_BUS_NAME_(BusName)::NAME; \ + static void emit(Arg0 arg0, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) { \ + ::extra2d::event::broadcast(arg0, arg1, arg2, arg3, arg4); \ + } \ + }; + +/** + * @brief 声明六参数事件 + */ +#define DECLARE_EVENT_6(EventName, BusName, Arg0, Arg1, Arg2, Arg3, Arg4, \ + Arg5) \ + struct EventName \ + : ::extra2d::event::EventTrait { \ + using Listener = ::extra2d::event::Listener; \ + static constexpr const char *NAME = #EventName; \ + static constexpr const char *BUS_NAME = \ + E2D_EVENT_BUS_NAME_(BusName)::NAME; \ + static void emit(Arg0 arg0, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, \ + Arg5 arg5) { \ + ::extra2d::event::broadcast(arg0, arg1, arg2, arg3, arg4, \ + arg5); \ + } \ + }; + +/** + * @brief 声明七参数事件 + */ +#define DECLARE_EVENT_7(EventName, BusName, Arg0, Arg1, Arg2, Arg3, Arg4, \ + Arg5, Arg6) \ + struct EventName \ + : ::extra2d::event::EventTrait { \ + using Listener = ::extra2d::event::Listener; \ + static constexpr const char *NAME = #EventName; \ + static constexpr const char *BUS_NAME = \ + E2D_EVENT_BUS_NAME_(BusName)::NAME; \ + static void emit(Arg0 arg0, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, \ + Arg5 arg5, Arg6 arg6) { \ + ::extra2d::event::broadcast(arg0, arg1, arg2, arg3, arg4, \ + arg5, arg6); \ + } \ + }; + +/** + * @brief 声明八参数事件 + */ +#define DECLARE_EVENT_8(EventName, BusName, Arg0, Arg1, Arg2, Arg3, Arg4, \ + Arg5, Arg6, Arg7) \ + struct EventName \ + : ::extra2d::event::EventTrait { \ + using Listener = ::extra2d::event::Listener; \ + static constexpr const char *NAME = #EventName; \ + static constexpr const char *BUS_NAME = \ + E2D_EVENT_BUS_NAME_(BusName)::NAME; \ + static void emit(Arg0 arg0, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, \ + Arg5 arg5, Arg6 arg6, Arg7 arg7) { \ + ::extra2d::event::broadcast(arg0, arg1, arg2, arg3, arg4, \ + arg5, arg6, arg7); \ + } \ + }; diff --git a/include/core/event/events.h b/include/event/events.h similarity index 93% rename from include/core/event/events.h rename to include/event/events.h index 8b432fa..22a2a80 100644 --- a/include/core/event/events.h +++ b/include/event/events.h @@ -1,8 +1,9 @@ #pragma once -#include -#include +#include #include +#include + namespace extra2d::events { @@ -138,25 +139,25 @@ DECLARE_EVENT_1(OnMouseWheel, Engine, int32) * @brief 触摸开始事件 * @param touch 触摸点信息 */ -DECLARE_EVENT_1(OnTouchBegan, Engine, const TouchPoint&) +DECLARE_EVENT_1(OnTouchBegan, Engine, const TouchPoint &) /** * @brief 触摸移动事件 * @param touch 触摸点信息 */ -DECLARE_EVENT_1(OnTouchMoved, Engine, const TouchPoint&) +DECLARE_EVENT_1(OnTouchMoved, Engine, const TouchPoint &) /** * @brief 触摸结束事件 * @param touch 触摸点信息 */ -DECLARE_EVENT_1(OnTouchEnded, Engine, const TouchPoint&) +DECLARE_EVENT_1(OnTouchEnded, Engine, const TouchPoint &) /** * @brief 触摸取消事件 * @param touch 触摸点信息 */ -DECLARE_EVENT_1(OnTouchCancelled, Engine, const TouchPoint&) +DECLARE_EVENT_1(OnTouchCancelled, Engine, const TouchPoint &) // ============================================================================ // 场景事件 diff --git a/include/extra2d.h b/include/extra2d.h index 47615d8..b3de0b3 100644 --- a/include/extra2d.h +++ b/include/extra2d.h @@ -23,10 +23,15 @@ #include // Platform -#include -#include -#include #include +#include +#include +#include + + +// Event +#include +#include // Utils #include diff --git a/src/app/application.cpp b/src/app/application.cpp index fa5c26c..c291a46 100644 --- a/src/app/application.cpp +++ b/src/app/application.cpp @@ -1,13 +1,14 @@ #include #include -#include #include +#include #include #include #include #include #include + #include #include diff --git a/src/core/event/event_bus.cpp b/src/core/event/event_bus.cpp deleted file mode 100644 index 925d852..0000000 --- a/src/core/event/event_bus.cpp +++ /dev/null @@ -1,96 +0,0 @@ -#include - -namespace extra2d::event { - -ListenerContainer::~ListenerContainer() { - ListenerEntry* curr = listenerList_; - while (curr) { - ListenerEntry* next = curr->next; - delete curr; - curr = next; - } - - curr = listenersToAdd_; - while (curr) { - ListenerEntry* next = curr->next; - delete curr; - curr = next; - } - - for (auto* entry : listenersToRemove_) { - delete entry; - } -} - -void ListenerContainer::addListener(ListenerBase* listener) { - if (!listener || !listener->entry_) return; - - if (broadcasting_ > 0) { - listener->entry_->next = listenersToAdd_; - listenersToAdd_ = listener->entry_; - } else { - listener->entry_->next = listenerList_; - listener->entry_->prev = nullptr; - if (listenerList_) { - listenerList_->prev = listener->entry_; - } - listenerList_ = listener->entry_; - } -} - -void ListenerContainer::removeListener(ListenerBase* listener) { - if (!listener || !listener->entry_) return; - - if (broadcasting_ > 0) { - listenersToRemove_.push_back(listener->entry_); - listener->entry_->listener = nullptr; - } else { - if (listener->entry_->prev) { - listener->entry_->prev->next = listener->entry_->next; - } else { - listenerList_ = listener->entry_->next; - } - - if (listener->entry_->next) { - listener->entry_->next->prev = listener->entry_->prev; - } - - delete listener->entry_; - listener->entry_ = nullptr; - } -} - -void ListenerContainer::processPendingListeners() { - while (listenersToAdd_) { - ListenerEntry* entry = listenersToAdd_; - listenersToAdd_ = entry->next; - - entry->next = listenerList_; - entry->prev = nullptr; - if (listenerList_) { - listenerList_->prev = entry; - } - listenerList_ = entry; - } - - for (auto* entry : listenersToRemove_) { - if (entry->prev) { - entry->prev->next = entry->next; - } else { - listenerList_ = entry->next; - } - - if (entry->next) { - entry->next->prev = entry->prev; - } - - delete entry; - } - listenersToRemove_.clear(); -} - -bool ListenerContainer::hasPendingListeners() const { - return listenersToAdd_ != nullptr || !listenersToRemove_.empty(); -} - -} // namespace extra2d::event diff --git a/src/core/scheduler.cpp b/src/core/scheduler.cpp index 7af6562..c8937cf 100644 --- a/src/core/scheduler.cpp +++ b/src/core/scheduler.cpp @@ -1,5 +1,7 @@ #include #include +#include +#include namespace extra2d { @@ -76,6 +78,35 @@ private: } +// SafePriorityQueue 实现 +void Scheduler::SafePriorityQueue::push(const UpdateEntry& entry) { + std::lock_guard lock(mutex_); + queue_.push(entry); +} + +bool Scheduler::SafePriorityQueue::pop(UpdateEntry& entry) { + std::lock_guard lock(mutex_); + if (queue_.empty()) return false; + entry = queue_.top(); + queue_.pop(); + return true; +} + +bool Scheduler::SafePriorityQueue::empty() const { + std::lock_guard lock(mutex_); + return queue_.empty(); +} + +size_t Scheduler::SafePriorityQueue::size() const { + std::lock_guard lock(mutex_); + return queue_.size(); +} + +void Scheduler::SafePriorityQueue::clear() { + std::lock_guard lock(mutex_); + while (!queue_.empty()) queue_.pop(); +} + Scheduler& Scheduler::inst() { static Scheduler instance; return instance; @@ -84,9 +115,10 @@ Scheduler& Scheduler::inst() { TimerHdl Scheduler::scheduleUpdate(TimerTarget* target, int pri) { if (!target) return INVALID_HDL; + std::lock_guard lock(updateIndexMutex_); UpdateEntry entry{target, pri, false, false}; updates_.push_back(entry); - updateIndex_.insert({target, updates_.size() - 1}); + updateIndex_[target] = updates_.size() - 1; return genHdl(); } @@ -94,13 +126,14 @@ TimerHdl Scheduler::scheduleUpdate(TimerTarget* target, int pri) { void Scheduler::unscheduleUpdate(TimerTarget* target) { if (!target) return; - tbb::concurrent_hash_map::accessor acc; - if (updateIndex_.find(acc, target)) { - size_t idx = acc->second; + std::lock_guard lock(updateIndexMutex_); + auto it = updateIndex_.find(target); + if (it != updateIndex_.end()) { + size_t idx = it->second; if (idx < updates_.size()) { updates_[idx].markedForDel = true; } - updateIndex_.erase(acc); + updateIndex_.erase(it); } } @@ -111,7 +144,10 @@ TimerHdl Scheduler::schedule(Cb cb, float interval, uint32 repeat, float delay) TimerHdl hdl = genHdl(); timer->hdl_ = hdl; - timers_.insert({hdl, timer}); + { + std::lock_guard lock(timersMutex_); + timers_[hdl] = timer; + } return hdl; } @@ -122,7 +158,10 @@ TimerHdl Scheduler::scheduleOnce(VoidCb cb, float delay) { TimerHdl hdl = genHdl(); timer->hdl_ = hdl; - timers_.insert({hdl, timer}); + { + std::lock_guard lock(timersMutex_); + timers_[hdl] = timer; + } return hdl; } @@ -131,26 +170,36 @@ TimerHdl Scheduler::scheduleForever(Cb cb, float interval) { } void Scheduler::unschedule(TimerHdl hdl) { + std::lock_guard lock(timersMutex_); timers_.erase(hdl); } void Scheduler::unscheduleAll() { - timers_.clear(); - updates_.clear(); - updateIndex_.clear(); + { + std::lock_guard lock(timersMutex_); + timers_.clear(); + } + { + std::lock_guard lock(updateIndexMutex_); + updates_.clear(); + updateIndex_.clear(); + } + updateQueue_.clear(); } void Scheduler::pause(TimerHdl hdl) { - tbb::concurrent_hash_map>::accessor acc; - if (timers_.find(acc, hdl)) { - acc->second->pause(); + std::lock_guard lock(timersMutex_); + auto it = timers_.find(hdl); + if (it != timers_.end()) { + it->second->pause(); } } void Scheduler::resume(TimerHdl hdl) { - tbb::concurrent_hash_map>::accessor acc; - if (timers_.find(acc, hdl)) { - acc->second->resume(); + std::lock_guard lock(timersMutex_); + auto it = timers_.find(hdl); + if (it != timers_.end()) { + it->second->resume(); } } @@ -159,29 +208,37 @@ void Scheduler::update(float dt) { locked_ = true; - for (auto& entry : updates_) { - if (!entry.markedForDel && !entry.paused && entry.target) { - entry.target->update(scaledDt); + // 更新所有 update 回调 + { + std::lock_guard lock(updateIndexMutex_); + for (auto& entry : updates_) { + if (!entry.markedForDel && !entry.paused && entry.target) { + entry.target->update(scaledDt); + } } + + updates_.erase( + std::remove_if(updates_.begin(), updates_.end(), + [](const UpdateEntry& e) { return e.markedForDel; }), + updates_.end() + ); } - updates_.erase( - std::remove_if(updates_.begin(), updates_.end(), - [](const UpdateEntry& e) { return e.markedForDel; }), - updates_.end() - ); - + // 更新定时器 std::vector toRemove; - for (auto it = timers_.begin(); it != timers_.end(); ++it) { - auto& timer = it->second; - timer->update(scaledDt); - if (timer->isDone()) { - toRemove.push_back(it->first); + { + std::lock_guard lock(timersMutex_); + for (auto it = timers_.begin(); it != timers_.end(); ++it) { + auto& timer = it->second; + timer->update(scaledDt); + if (timer->isDone()) { + toRemove.push_back(it->first); + } } - } - for (auto hdl : toRemove) { - timers_.erase(hdl); + for (auto hdl : toRemove) { + timers_.erase(hdl); + } } locked_ = false; @@ -192,44 +249,69 @@ void Scheduler::updateParallel(float dt) { locked_ = true; - tbb::parallel_for(tbb::blocked_range(0, updates_.size()), - [this, scaledDt](const tbb::blocked_range& range) { - for (size_t i = range.begin(); i != range.end(); ++i) { - auto& entry = updates_[i]; - if (!entry.markedForDel && !entry.paused && entry.target) { - entry.target->update(scaledDt); + // 并行更新所有 update 回调(使用标准库线程) + { + std::lock_guard lock(updateIndexMutex_); + size_t numThreads = std::thread::hardware_concurrency(); + if (numThreads == 0) numThreads = 4; + + size_t batchSize = updates_.size() / numThreads; + if (batchSize == 0) batchSize = 1; + + std::vector> futures; + + for (size_t t = 0; t < numThreads && t * batchSize < updates_.size(); ++t) { + size_t start = t * batchSize; + size_t end = (t == numThreads - 1) ? updates_.size() : (t + 1) * batchSize; + + futures.push_back(std::async(std::launch::async, [this, start, end, scaledDt]() { + for (size_t i = start; i < end; ++i) { + auto& entry = updates_[i]; + if (!entry.markedForDel && !entry.paused && entry.target) { + entry.target->update(scaledDt); + } } - } - }); - - updates_.erase( - std::remove_if(updates_.begin(), updates_.end(), - [](const UpdateEntry& e) { return e.markedForDel; }), - updates_.end() - ); - - std::vector toRemove; - for (auto it = timers_.begin(); it != timers_.end(); ++it) { - auto& timer = it->second; - timer->update(scaledDt); - if (timer->isDone()) { - toRemove.push_back(it->first); + })); } + + for (auto& f : futures) { + f.wait(); + } + + updates_.erase( + std::remove_if(updates_.begin(), updates_.end(), + [](const UpdateEntry& e) { return e.markedForDel; }), + updates_.end() + ); } - for (auto hdl : toRemove) { - timers_.erase(hdl); + // 更新定时器 + std::vector toRemove; + { + std::lock_guard lock(timersMutex_); + for (auto it = timers_.begin(); it != timers_.end(); ++it) { + auto& timer = it->second; + timer->update(scaledDt); + if (timer->isDone()) { + toRemove.push_back(it->first); + } + } + + for (auto hdl : toRemove) { + timers_.erase(hdl); + } } locked_ = false; } bool Scheduler::isScheduled(TimerHdl hdl) const { - tbb::concurrent_hash_map>::const_accessor acc; - return timers_.find(acc, hdl); + std::lock_guard lock(timersMutex_); + return timers_.find(hdl) != timers_.end(); } size_t Scheduler::count() const { + std::lock_guard lock(timersMutex_); return timers_.size(); } diff --git a/src/core/service.cpp b/src/core/service.cpp index b58b052..fb811db 100644 --- a/src/core/service.cpp +++ b/src/core/service.cpp @@ -10,26 +10,29 @@ SvcMgr& SvcMgr::inst() { void SvcMgr::reg(IService* svc) { if (!svc) return; - SvcMap::accessor acc; - svcMap_.insert(acc, svc->name()); - acc->second = Ptr(svc); + + std::lock_guard lock(svcMapMutex_); + svcMap_[svc->name()] = Ptr(svc); sortSvcs(); } void SvcMgr::unreg(const char* name) { + std::lock_guard lock(svcMapMutex_); svcMap_.erase(name); sortSvcs(); } Ptr SvcMgr::get(const char* name) { - SvcMap::const_accessor acc; - if (svcMap_.find(acc, name)) { - return acc->second; + std::lock_guard lock(svcMapMutex_); + auto it = svcMap_.find(name); + if (it != svcMap_.end()) { + return it->second; } return nullptr; } bool SvcMgr::initAll() { + std::lock_guard lock(svcMapMutex_); for (auto& svc : sortedSvcs_) { if (svc && svc->state_ == SvcState::None) { if (!svc->init()) { @@ -42,6 +45,7 @@ bool SvcMgr::initAll() { } void SvcMgr::pauseAll() { + std::lock_guard lock(svcMapMutex_); for (auto& svc : sortedSvcs_) { if (svc && svc->state_ == SvcState::Running) { svc->pause(); @@ -51,6 +55,7 @@ void SvcMgr::pauseAll() { } void SvcMgr::resumeAll() { + std::lock_guard lock(svcMapMutex_); for (auto& svc : sortedSvcs_) { if (svc && svc->state_ == SvcState::Paused) { svc->resume(); @@ -60,6 +65,7 @@ void SvcMgr::resumeAll() { } void SvcMgr::shutdownAll() { + std::lock_guard lock(svcMapMutex_); for (auto it = sortedSvcs_.rbegin(); it != sortedSvcs_.rend(); ++it) { if (*it && (*it)->state_ >= SvcState::Inited) { (*it)->shutdown(); @@ -69,6 +75,7 @@ void SvcMgr::shutdownAll() { } void SvcMgr::updateAll(float dt) { + std::lock_guard lock(svcMapMutex_); for (auto& svc : sortedSvcs_) { if (svc && svc->state_ >= SvcState::Inited && svc->isEnabled()) { if (svc->state_ == SvcState::Inited) { @@ -80,6 +87,7 @@ void SvcMgr::updateAll(float dt) { } void SvcMgr::lateUpdateAll(float dt) { + std::lock_guard lock(svcMapMutex_); for (auto& svc : sortedSvcs_) { if (svc && svc->state_ >= SvcState::Running && svc->isEnabled()) { svc->lateUpdate(dt); @@ -88,6 +96,7 @@ void SvcMgr::lateUpdateAll(float dt) { } void SvcMgr::fixedUpdateAll(float dt) { + std::lock_guard lock(svcMapMutex_); for (auto& svc : sortedSvcs_) { if (svc && svc->state_ >= SvcState::Running && svc->isEnabled()) { svc->fixedUpdate(dt); @@ -96,11 +105,12 @@ void SvcMgr::fixedUpdateAll(float dt) { } bool SvcMgr::has(const char* name) const { - SvcMap::const_accessor acc; - return svcMap_.find(acc, name); + std::lock_guard lock(svcMapMutex_); + return svcMap_.find(name) != svcMap_.end(); } size_t SvcMgr::count() const { + std::lock_guard lock(svcMapMutex_); return svcMap_.size(); } diff --git a/src/event/event_bus.cpp b/src/event/event_bus.cpp new file mode 100644 index 0000000..55f9ed4 --- /dev/null +++ b/src/event/event_bus.cpp @@ -0,0 +1,98 @@ +#include + +namespace extra2d::event { + +ListenerContainer::~ListenerContainer() { + ListenerEntry *curr = listenerList_; + while (curr) { + ListenerEntry *next = curr->next; + delete curr; + curr = next; + } + + curr = listenersToAdd_; + while (curr) { + ListenerEntry *next = curr->next; + delete curr; + curr = next; + } + + for (auto *entry : listenersToRemove_) { + delete entry; + } +} + +void ListenerContainer::addListener(ListenerBase *listener) { + if (!listener || !listener->entry_) + return; + + if (broadcasting_ > 0) { + listener->entry_->next = listenersToAdd_; + listenersToAdd_ = listener->entry_; + } else { + listener->entry_->next = listenerList_; + listener->entry_->prev = nullptr; + if (listenerList_) { + listenerList_->prev = listener->entry_; + } + listenerList_ = listener->entry_; + } +} + +void ListenerContainer::removeListener(ListenerBase *listener) { + if (!listener || !listener->entry_) + return; + + if (broadcasting_ > 0) { + listenersToRemove_.push_back(listener->entry_); + listener->entry_->listener = nullptr; + } else { + if (listener->entry_->prev) { + listener->entry_->prev->next = listener->entry_->next; + } else { + listenerList_ = listener->entry_->next; + } + + if (listener->entry_->next) { + listener->entry_->next->prev = listener->entry_->prev; + } + + delete listener->entry_; + listener->entry_ = nullptr; + } +} + +void ListenerContainer::processPendingListeners() { + while (listenersToAdd_) { + ListenerEntry *entry = listenersToAdd_; + listenersToAdd_ = entry->next; + + entry->next = listenerList_; + entry->prev = nullptr; + if (listenerList_) { + listenerList_->prev = entry; + } + listenerList_ = entry; + } + + for (auto *entry : listenersToRemove_) { + if (entry->prev) { + entry->prev->next = entry->next; + } else { + listenerList_ = entry->next; + } + + if (entry->next) { + entry->next->prev = entry->prev; + } + + delete entry; + } + listenersToRemove_.clear(); +} + +bool ListenerContainer::hasPendingListeners() const { + return listenersToAdd_ != nullptr || !listenersToRemove_.empty(); +} + +} // namespace extra2d::event diff --git a/third_party/tbb b/third_party/tbb deleted file mode 160000 index 492c01e..0000000 --- a/third_party/tbb +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 492c01ee2b906e945f08355787dfc015dd7cc505 diff --git a/xmake/engine.lua b/xmake/engine.lua index 1743216..8e7d665 100644 --- a/xmake/engine.lua +++ b/xmake/engine.lua @@ -8,44 +8,11 @@ local function get_current_plat() return get_config("plat") or os.host() end --- 定义 TBB 源码编译目标 -function define_tbb_target() - target("tbb") - set_kind("static") - set_languages("c++17") - - add_includedirs("third_party/tbb/include", {public = true}) - - add_files("third_party/tbb/src/tbb/*.cpp") - - add_defines("__TBB_BUILD=1") - add_defines("TBB_SUPPRESS_DEPRECATED_MESSAGES=1") - add_defines("TBB_USE_PROFILING_TOOLS=0") - - local plat = get_current_plat() - if plat == "mingw" then - -- TBB uses ANSI Windows APIs, don't define UNICODE - -- MinGW doesn't define LOAD_LIBRARY_SAFE_CURRENT_DIRS - add_defines("LOAD_LIBRARY_SAFE_CURRENT_DIRS=0x00002000") - elseif plat == "switch" then - add_defines("__TBB_USE_THREAD_SANITIZER=0") - add_defines("TBB_USE_ASSERT=0") - add_defines("TBB_USE_DEBUG=0") - end - - add_cxflags("-Wno-implicit-fallthrough", "-Wno-unused-function", "-Wno-unused-variable", {force = true}) - target_end() -end - -- 定义 Extra2D 引擎库目标 function define_extra2d_engine() - define_tbb_target() - target("extra2d") set_kind("static") - add_deps("tbb") - add_files("src/**.cpp") add_files("third_party/glad/src/glad.c") @@ -53,8 +20,6 @@ function define_extra2d_engine() add_includedirs("third_party/glad/include", {public = true}) add_includedirs("third_party", {public = true}) - add_defines("TBB_USE_PROFILING_TOOLS=0") - local plat = get_current_plat() if plat == "mingw" then add_defines("_UNICODE", "UNICODE")