refactor(core): 移除TBB依赖并重构事件系统和调度器

重构服务管理器和调度器,使用标准库替代TBB并发容器
将事件系统从core移动到独立event目录并优化实现
更新构建脚本移除TBB相关配置
添加线程安全队列实现并行调度
This commit is contained in:
ChestnutYueyue 2026-02-28 04:44:56 +08:00
parent 0761b55864
commit 5a3d0cd9de
14 changed files with 464 additions and 330 deletions

View File

@ -1,112 +0,0 @@
#pragma once
#include <core/event/event_bus.h>
#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<E2D_EVENT_BUS_NAME_(BusName)> { \
using Listener = ::extra2d::event::Listener<EventName>; \
static constexpr const char* NAME = #EventName; \
static constexpr const char* BUS_NAME = E2D_EVENT_BUS_NAME_(BusName)::NAME; \
static void emit() { ::extra2d::event::broadcast<EventName>(); } \
};
/**
* @brief
*/
#define DECLARE_EVENT_1(EventName, BusName, Arg0) \
struct EventName : ::extra2d::event::EventTrait<E2D_EVENT_BUS_NAME_(BusName), Arg0> { \
using Listener = ::extra2d::event::Listener<EventName>; \
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<EventName>(arg0); } \
};
/**
* @brief
*/
#define DECLARE_EVENT_2(EventName, BusName, Arg0, Arg1) \
struct EventName : ::extra2d::event::EventTrait<E2D_EVENT_BUS_NAME_(BusName), Arg0, Arg1> { \
using Listener = ::extra2d::event::Listener<EventName>; \
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<EventName>(arg0, arg1); } \
};
/**
* @brief
*/
#define DECLARE_EVENT_3(EventName, BusName, Arg0, Arg1, Arg2) \
struct EventName : ::extra2d::event::EventTrait<E2D_EVENT_BUS_NAME_(BusName), Arg0, Arg1, Arg2> { \
using Listener = ::extra2d::event::Listener<EventName>; \
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<EventName>(arg0, arg1, arg2); } \
};
/**
* @brief
*/
#define DECLARE_EVENT_4(EventName, BusName, Arg0, Arg1, Arg2, Arg3) \
struct EventName : ::extra2d::event::EventTrait<E2D_EVENT_BUS_NAME_(BusName), Arg0, Arg1, Arg2, Arg3> { \
using Listener = ::extra2d::event::Listener<EventName>; \
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<EventName>(arg0, arg1, arg2, arg3); } \
};
/**
* @brief
*/
#define DECLARE_EVENT_5(EventName, BusName, Arg0, Arg1, Arg2, Arg3, Arg4) \
struct EventName : ::extra2d::event::EventTrait<E2D_EVENT_BUS_NAME_(BusName), Arg0, Arg1, Arg2, Arg3, Arg4> { \
using Listener = ::extra2d::event::Listener<EventName>; \
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<EventName>(arg0, arg1, arg2, arg3, arg4); } \
};
/**
* @brief
*/
#define DECLARE_EVENT_6(EventName, BusName, Arg0, Arg1, Arg2, Arg3, Arg4, Arg5) \
struct EventName : ::extra2d::event::EventTrait<E2D_EVENT_BUS_NAME_(BusName), Arg0, Arg1, Arg2, Arg3, Arg4, Arg5> { \
using Listener = ::extra2d::event::Listener<EventName>; \
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<EventName>(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<E2D_EVENT_BUS_NAME_(BusName), Arg0, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6> { \
using Listener = ::extra2d::event::Listener<EventName>; \
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<EventName>(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<E2D_EVENT_BUS_NAME_(BusName), Arg0, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7> { \
using Listener = ::extra2d::event::Listener<EventName>; \
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<EventName>(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); } \
};

View File

@ -4,12 +4,11 @@
#include <types/ptr/ref_counted.h> #include <types/ptr/ref_counted.h>
#include <types/ptr/intrusive_ptr.h> #include <types/ptr/intrusive_ptr.h>
#include <types/const/priority.h> #include <types/const/priority.h>
#include <tbb/concurrent_hash_map.h>
#include <tbb/concurrent_priority_queue.h>
#include <tbb/parallel_for.h>
#include <tbb/blocked_range.h>
#include <atomic> #include <atomic>
#include <vector> #include <vector>
#include <unordered_map>
#include <queue>
#include <mutex>
namespace extra2d { namespace extra2d {
@ -65,7 +64,7 @@ protected:
/** /**
* @brief * @brief
* *
* TBB 线 update * 线 update
*/ */
class Scheduler { class Scheduler {
public: public:
@ -107,10 +106,27 @@ private:
bool operator<(const UpdateEntry& o) const { return pri > o.pri; } 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<UpdateEntry> queue_;
};
std::vector<UpdateEntry> updates_; std::vector<UpdateEntry> updates_;
tbb::concurrent_hash_map<TimerTarget*, size_t> updateIndex_; std::unordered_map<TimerTarget*, size_t> updateIndex_;
tbb::concurrent_hash_map<TimerHdl, Ptr<Timer>> timers_; mutable std::mutex updateIndexMutex_;
tbb::concurrent_priority_queue<UpdateEntry> updateQueue_;
std::unordered_map<TimerHdl, Ptr<Timer>> timers_;
mutable std::mutex timersMutex_;
SafePriorityQueue updateQueue_;
std::atomic<TimerHdl> nextHdl_{1}; std::atomic<TimerHdl> nextHdl_{1};
std::atomic<float> timeScale_{1.0f}; std::atomic<float> timeScale_{1.0f};

View File

@ -6,7 +6,8 @@
#include <types/const/priority.h> #include <types/const/priority.h>
#include <string> #include <string>
#include <vector> #include <vector>
#include <tbb/concurrent_hash_map.h> #include <unordered_map>
#include <mutex>
namespace extra2d { namespace extra2d {
@ -88,8 +89,10 @@ public:
private: private:
SvcMgr() = default; SvcMgr() = default;
using SvcMap = tbb::concurrent_hash_map<std::string, Ptr<IService>>; using SvcMap = std::unordered_map<std::string, Ptr<IService>>;
SvcMap svcMap_; SvcMap svcMap_;
mutable std::mutex svcMapMutex_;
std::vector<Ptr<IService>> sortedSvcs_; std::vector<Ptr<IService>> sortedSvcs_;
void sortSvcs(); void sortSvcs();

View File

@ -0,0 +1,162 @@
#pragma once
#include <event/event_bus.h>
#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<E2D_EVENT_BUS_NAME_(BusName)> { \
using Listener = ::extra2d::event::Listener<EventName>; \
static constexpr const char *NAME = #EventName; \
static constexpr const char *BUS_NAME = \
E2D_EVENT_BUS_NAME_(BusName)::NAME; \
static void emit() { ::extra2d::event::broadcast<EventName>(); } \
};
/**
* @brief
*/
#define DECLARE_EVENT_1(EventName, BusName, Arg0) \
struct EventName \
: ::extra2d::event::EventTrait<E2D_EVENT_BUS_NAME_(BusName), Arg0> { \
using Listener = ::extra2d::event::Listener<EventName>; \
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<EventName>(arg0); \
} \
};
/**
* @brief
*/
#define DECLARE_EVENT_2(EventName, BusName, Arg0, Arg1) \
struct EventName \
: ::extra2d::event::EventTrait<E2D_EVENT_BUS_NAME_(BusName), Arg0, \
Arg1> { \
using Listener = ::extra2d::event::Listener<EventName>; \
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<EventName>(arg0, arg1); \
} \
};
/**
* @brief
*/
#define DECLARE_EVENT_3(EventName, BusName, Arg0, Arg1, Arg2) \
struct EventName \
: ::extra2d::event::EventTrait<E2D_EVENT_BUS_NAME_(BusName), Arg0, Arg1, \
Arg2> { \
using Listener = ::extra2d::event::Listener<EventName>; \
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<EventName>(arg0, arg1, arg2); \
} \
};
/**
* @brief
*/
#define DECLARE_EVENT_4(EventName, BusName, Arg0, Arg1, Arg2, Arg3) \
struct EventName \
: ::extra2d::event::EventTrait<E2D_EVENT_BUS_NAME_(BusName), Arg0, Arg1, \
Arg2, Arg3> { \
using Listener = ::extra2d::event::Listener<EventName>; \
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<EventName>(arg0, arg1, arg2, arg3); \
} \
};
/**
* @brief
*/
#define DECLARE_EVENT_5(EventName, BusName, Arg0, Arg1, Arg2, Arg3, Arg4) \
struct EventName \
: ::extra2d::event::EventTrait<E2D_EVENT_BUS_NAME_(BusName), Arg0, Arg1, \
Arg2, Arg3, Arg4> { \
using Listener = ::extra2d::event::Listener<EventName>; \
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<EventName>(arg0, arg1, arg2, arg3, arg4); \
} \
};
/**
* @brief
*/
#define DECLARE_EVENT_6(EventName, BusName, Arg0, Arg1, Arg2, Arg3, Arg4, \
Arg5) \
struct EventName \
: ::extra2d::event::EventTrait<E2D_EVENT_BUS_NAME_(BusName), Arg0, Arg1, \
Arg2, Arg3, Arg4, Arg5> { \
using Listener = ::extra2d::event::Listener<EventName>; \
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<EventName>(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<E2D_EVENT_BUS_NAME_(BusName), Arg0, Arg1, \
Arg2, Arg3, Arg4, Arg5, Arg6> { \
using Listener = ::extra2d::event::Listener<EventName>; \
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<EventName>(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<E2D_EVENT_BUS_NAME_(BusName), Arg0, Arg1, \
Arg2, Arg3, Arg4, Arg5, Arg6, Arg7> { \
using Listener = ::extra2d::event::Listener<EventName>; \
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<EventName>(arg0, arg1, arg2, arg3, arg4, \
arg5, arg6, arg7); \
} \
};

View File

@ -1,8 +1,9 @@
#pragma once #pragma once
#include <core/event/event_bus_macros.h> #include <event/event_bus_macros.h>
#include <types/base/types.h>
#include <platform/input.h> #include <platform/input.h>
#include <types/base/types.h>
namespace extra2d::events { namespace extra2d::events {
@ -138,25 +139,25 @@ DECLARE_EVENT_1(OnMouseWheel, Engine, int32)
* @brief * @brief
* @param touch * @param touch
*/ */
DECLARE_EVENT_1(OnTouchBegan, Engine, const TouchPoint&) DECLARE_EVENT_1(OnTouchBegan, Engine, const TouchPoint &)
/** /**
* @brief * @brief
* @param touch * @param touch
*/ */
DECLARE_EVENT_1(OnTouchMoved, Engine, const TouchPoint&) DECLARE_EVENT_1(OnTouchMoved, Engine, const TouchPoint &)
/** /**
* @brief * @brief
* @param touch * @param touch
*/ */
DECLARE_EVENT_1(OnTouchEnded, Engine, const TouchPoint&) DECLARE_EVENT_1(OnTouchEnded, Engine, const TouchPoint &)
/** /**
* @brief * @brief
* @param touch * @param touch
*/ */
DECLARE_EVENT_1(OnTouchCancelled, Engine, const TouchPoint&) DECLARE_EVENT_1(OnTouchCancelled, Engine, const TouchPoint &)
// ============================================================================ // ============================================================================
// 场景事件 // 场景事件

View File

@ -23,10 +23,15 @@
#include <core/service.h> #include <core/service.h>
// Platform // Platform
#include <platform/sdl2.h>
#include <platform/input.h>
#include <platform/window.h>
#include <platform/file.h> #include <platform/file.h>
#include <platform/input.h>
#include <platform/sdl2.h>
#include <platform/window.h>
// Event
#include <event/event_bus.h>
#include <event/events.h>
// Utils // Utils
#include <utils/logger.h> #include <utils/logger.h>

View File

@ -1,13 +1,14 @@
#include <app/application.h> #include <app/application.h>
#include <core/director.h> #include <core/director.h>
#include <core/event/events.h>
#include <core/service.h> #include <core/service.h>
#include <event/events.h>
#include <platform/file.h> #include <platform/file.h>
#include <platform/input.h> #include <platform/input.h>
#include <platform/sdl2.h> #include <platform/sdl2.h>
#include <platform/window.h> #include <platform/window.h>
#include <utils/logger.h> #include <utils/logger.h>
#include <chrono> #include <chrono>
#include <thread> #include <thread>

View File

@ -1,96 +0,0 @@
#include <core/event/event_bus.h>
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

View File

@ -1,5 +1,7 @@
#include <core/scheduler.h> #include <core/scheduler.h>
#include <algorithm> #include <algorithm>
#include <thread>
#include <future>
namespace extra2d { namespace extra2d {
@ -76,6 +78,35 @@ private:
} }
// SafePriorityQueue 实现
void Scheduler::SafePriorityQueue::push(const UpdateEntry& entry) {
std::lock_guard<std::mutex> lock(mutex_);
queue_.push(entry);
}
bool Scheduler::SafePriorityQueue::pop(UpdateEntry& entry) {
std::lock_guard<std::mutex> lock(mutex_);
if (queue_.empty()) return false;
entry = queue_.top();
queue_.pop();
return true;
}
bool Scheduler::SafePriorityQueue::empty() const {
std::lock_guard<std::mutex> lock(mutex_);
return queue_.empty();
}
size_t Scheduler::SafePriorityQueue::size() const {
std::lock_guard<std::mutex> lock(mutex_);
return queue_.size();
}
void Scheduler::SafePriorityQueue::clear() {
std::lock_guard<std::mutex> lock(mutex_);
while (!queue_.empty()) queue_.pop();
}
Scheduler& Scheduler::inst() { Scheduler& Scheduler::inst() {
static Scheduler instance; static Scheduler instance;
return instance; return instance;
@ -84,9 +115,10 @@ Scheduler& Scheduler::inst() {
TimerHdl Scheduler::scheduleUpdate(TimerTarget* target, int pri) { TimerHdl Scheduler::scheduleUpdate(TimerTarget* target, int pri) {
if (!target) return INVALID_HDL; if (!target) return INVALID_HDL;
std::lock_guard<std::mutex> lock(updateIndexMutex_);
UpdateEntry entry{target, pri, false, false}; UpdateEntry entry{target, pri, false, false};
updates_.push_back(entry); updates_.push_back(entry);
updateIndex_.insert({target, updates_.size() - 1}); updateIndex_[target] = updates_.size() - 1;
return genHdl(); return genHdl();
} }
@ -94,13 +126,14 @@ TimerHdl Scheduler::scheduleUpdate(TimerTarget* target, int pri) {
void Scheduler::unscheduleUpdate(TimerTarget* target) { void Scheduler::unscheduleUpdate(TimerTarget* target) {
if (!target) return; if (!target) return;
tbb::concurrent_hash_map<TimerTarget*, size_t>::accessor acc; std::lock_guard<std::mutex> lock(updateIndexMutex_);
if (updateIndex_.find(acc, target)) { auto it = updateIndex_.find(target);
size_t idx = acc->second; if (it != updateIndex_.end()) {
size_t idx = it->second;
if (idx < updates_.size()) { if (idx < updates_.size()) {
updates_[idx].markedForDel = true; 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(); TimerHdl hdl = genHdl();
timer->hdl_ = hdl; timer->hdl_ = hdl;
timers_.insert({hdl, timer}); {
std::lock_guard<std::mutex> lock(timersMutex_);
timers_[hdl] = timer;
}
return hdl; return hdl;
} }
@ -122,7 +158,10 @@ TimerHdl Scheduler::scheduleOnce(VoidCb cb, float delay) {
TimerHdl hdl = genHdl(); TimerHdl hdl = genHdl();
timer->hdl_ = hdl; timer->hdl_ = hdl;
timers_.insert({hdl, timer}); {
std::lock_guard<std::mutex> lock(timersMutex_);
timers_[hdl] = timer;
}
return hdl; return hdl;
} }
@ -131,26 +170,36 @@ TimerHdl Scheduler::scheduleForever(Cb cb, float interval) {
} }
void Scheduler::unschedule(TimerHdl hdl) { void Scheduler::unschedule(TimerHdl hdl) {
std::lock_guard<std::mutex> lock(timersMutex_);
timers_.erase(hdl); timers_.erase(hdl);
} }
void Scheduler::unscheduleAll() { void Scheduler::unscheduleAll() {
{
std::lock_guard<std::mutex> lock(timersMutex_);
timers_.clear(); timers_.clear();
}
{
std::lock_guard<std::mutex> lock(updateIndexMutex_);
updates_.clear(); updates_.clear();
updateIndex_.clear(); updateIndex_.clear();
}
updateQueue_.clear();
} }
void Scheduler::pause(TimerHdl hdl) { void Scheduler::pause(TimerHdl hdl) {
tbb::concurrent_hash_map<TimerHdl, Ptr<Timer>>::accessor acc; std::lock_guard<std::mutex> lock(timersMutex_);
if (timers_.find(acc, hdl)) { auto it = timers_.find(hdl);
acc->second->pause(); if (it != timers_.end()) {
it->second->pause();
} }
} }
void Scheduler::resume(TimerHdl hdl) { void Scheduler::resume(TimerHdl hdl) {
tbb::concurrent_hash_map<TimerHdl, Ptr<Timer>>::accessor acc; std::lock_guard<std::mutex> lock(timersMutex_);
if (timers_.find(acc, hdl)) { auto it = timers_.find(hdl);
acc->second->resume(); if (it != timers_.end()) {
it->second->resume();
} }
} }
@ -159,6 +208,9 @@ void Scheduler::update(float dt) {
locked_ = true; locked_ = true;
// 更新所有 update 回调
{
std::lock_guard<std::mutex> lock(updateIndexMutex_);
for (auto& entry : updates_) { for (auto& entry : updates_) {
if (!entry.markedForDel && !entry.paused && entry.target) { if (!entry.markedForDel && !entry.paused && entry.target) {
entry.target->update(scaledDt); entry.target->update(scaledDt);
@ -170,8 +222,12 @@ void Scheduler::update(float dt) {
[](const UpdateEntry& e) { return e.markedForDel; }), [](const UpdateEntry& e) { return e.markedForDel; }),
updates_.end() updates_.end()
); );
}
// 更新定时器
std::vector<TimerHdl> toRemove; std::vector<TimerHdl> toRemove;
{
std::lock_guard<std::mutex> lock(timersMutex_);
for (auto it = timers_.begin(); it != timers_.end(); ++it) { for (auto it = timers_.begin(); it != timers_.end(); ++it) {
auto& timer = it->second; auto& timer = it->second;
timer->update(scaledDt); timer->update(scaledDt);
@ -183,6 +239,7 @@ void Scheduler::update(float dt) {
for (auto hdl : toRemove) { for (auto hdl : toRemove) {
timers_.erase(hdl); timers_.erase(hdl);
} }
}
locked_ = false; locked_ = false;
} }
@ -192,23 +249,46 @@ void Scheduler::updateParallel(float dt) {
locked_ = true; locked_ = true;
tbb::parallel_for(tbb::blocked_range<size_t>(0, updates_.size()), // 并行更新所有 update 回调(使用标准库线程)
[this, scaledDt](const tbb::blocked_range<size_t>& range) { {
for (size_t i = range.begin(); i != range.end(); ++i) { std::lock_guard<std::mutex> 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<std::future<void>> 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]; auto& entry = updates_[i];
if (!entry.markedForDel && !entry.paused && entry.target) { if (!entry.markedForDel && !entry.paused && entry.target) {
entry.target->update(scaledDt); entry.target->update(scaledDt);
} }
} }
}); }));
}
for (auto& f : futures) {
f.wait();
}
updates_.erase( updates_.erase(
std::remove_if(updates_.begin(), updates_.end(), std::remove_if(updates_.begin(), updates_.end(),
[](const UpdateEntry& e) { return e.markedForDel; }), [](const UpdateEntry& e) { return e.markedForDel; }),
updates_.end() updates_.end()
); );
}
// 更新定时器
std::vector<TimerHdl> toRemove; std::vector<TimerHdl> toRemove;
{
std::lock_guard<std::mutex> lock(timersMutex_);
for (auto it = timers_.begin(); it != timers_.end(); ++it) { for (auto it = timers_.begin(); it != timers_.end(); ++it) {
auto& timer = it->second; auto& timer = it->second;
timer->update(scaledDt); timer->update(scaledDt);
@ -220,16 +300,18 @@ void Scheduler::updateParallel(float dt) {
for (auto hdl : toRemove) { for (auto hdl : toRemove) {
timers_.erase(hdl); timers_.erase(hdl);
} }
}
locked_ = false; locked_ = false;
} }
bool Scheduler::isScheduled(TimerHdl hdl) const { bool Scheduler::isScheduled(TimerHdl hdl) const {
tbb::concurrent_hash_map<TimerHdl, Ptr<Timer>>::const_accessor acc; std::lock_guard<std::mutex> lock(timersMutex_);
return timers_.find(acc, hdl); return timers_.find(hdl) != timers_.end();
} }
size_t Scheduler::count() const { size_t Scheduler::count() const {
std::lock_guard<std::mutex> lock(timersMutex_);
return timers_.size(); return timers_.size();
} }

View File

@ -10,26 +10,29 @@ SvcMgr& SvcMgr::inst() {
void SvcMgr::reg(IService* svc) { void SvcMgr::reg(IService* svc) {
if (!svc) return; if (!svc) return;
SvcMap::accessor acc;
svcMap_.insert(acc, svc->name()); std::lock_guard<std::mutex> lock(svcMapMutex_);
acc->second = Ptr<IService>(svc); svcMap_[svc->name()] = Ptr<IService>(svc);
sortSvcs(); sortSvcs();
} }
void SvcMgr::unreg(const char* name) { void SvcMgr::unreg(const char* name) {
std::lock_guard<std::mutex> lock(svcMapMutex_);
svcMap_.erase(name); svcMap_.erase(name);
sortSvcs(); sortSvcs();
} }
Ptr<IService> SvcMgr::get(const char* name) { Ptr<IService> SvcMgr::get(const char* name) {
SvcMap::const_accessor acc; std::lock_guard<std::mutex> lock(svcMapMutex_);
if (svcMap_.find(acc, name)) { auto it = svcMap_.find(name);
return acc->second; if (it != svcMap_.end()) {
return it->second;
} }
return nullptr; return nullptr;
} }
bool SvcMgr::initAll() { bool SvcMgr::initAll() {
std::lock_guard<std::mutex> lock(svcMapMutex_);
for (auto& svc : sortedSvcs_) { for (auto& svc : sortedSvcs_) {
if (svc && svc->state_ == SvcState::None) { if (svc && svc->state_ == SvcState::None) {
if (!svc->init()) { if (!svc->init()) {
@ -42,6 +45,7 @@ bool SvcMgr::initAll() {
} }
void SvcMgr::pauseAll() { void SvcMgr::pauseAll() {
std::lock_guard<std::mutex> lock(svcMapMutex_);
for (auto& svc : sortedSvcs_) { for (auto& svc : sortedSvcs_) {
if (svc && svc->state_ == SvcState::Running) { if (svc && svc->state_ == SvcState::Running) {
svc->pause(); svc->pause();
@ -51,6 +55,7 @@ void SvcMgr::pauseAll() {
} }
void SvcMgr::resumeAll() { void SvcMgr::resumeAll() {
std::lock_guard<std::mutex> lock(svcMapMutex_);
for (auto& svc : sortedSvcs_) { for (auto& svc : sortedSvcs_) {
if (svc && svc->state_ == SvcState::Paused) { if (svc && svc->state_ == SvcState::Paused) {
svc->resume(); svc->resume();
@ -60,6 +65,7 @@ void SvcMgr::resumeAll() {
} }
void SvcMgr::shutdownAll() { void SvcMgr::shutdownAll() {
std::lock_guard<std::mutex> lock(svcMapMutex_);
for (auto it = sortedSvcs_.rbegin(); it != sortedSvcs_.rend(); ++it) { for (auto it = sortedSvcs_.rbegin(); it != sortedSvcs_.rend(); ++it) {
if (*it && (*it)->state_ >= SvcState::Inited) { if (*it && (*it)->state_ >= SvcState::Inited) {
(*it)->shutdown(); (*it)->shutdown();
@ -69,6 +75,7 @@ void SvcMgr::shutdownAll() {
} }
void SvcMgr::updateAll(float dt) { void SvcMgr::updateAll(float dt) {
std::lock_guard<std::mutex> lock(svcMapMutex_);
for (auto& svc : sortedSvcs_) { for (auto& svc : sortedSvcs_) {
if (svc && svc->state_ >= SvcState::Inited && svc->isEnabled()) { if (svc && svc->state_ >= SvcState::Inited && svc->isEnabled()) {
if (svc->state_ == SvcState::Inited) { if (svc->state_ == SvcState::Inited) {
@ -80,6 +87,7 @@ void SvcMgr::updateAll(float dt) {
} }
void SvcMgr::lateUpdateAll(float dt) { void SvcMgr::lateUpdateAll(float dt) {
std::lock_guard<std::mutex> lock(svcMapMutex_);
for (auto& svc : sortedSvcs_) { for (auto& svc : sortedSvcs_) {
if (svc && svc->state_ >= SvcState::Running && svc->isEnabled()) { if (svc && svc->state_ >= SvcState::Running && svc->isEnabled()) {
svc->lateUpdate(dt); svc->lateUpdate(dt);
@ -88,6 +96,7 @@ void SvcMgr::lateUpdateAll(float dt) {
} }
void SvcMgr::fixedUpdateAll(float dt) { void SvcMgr::fixedUpdateAll(float dt) {
std::lock_guard<std::mutex> lock(svcMapMutex_);
for (auto& svc : sortedSvcs_) { for (auto& svc : sortedSvcs_) {
if (svc && svc->state_ >= SvcState::Running && svc->isEnabled()) { if (svc && svc->state_ >= SvcState::Running && svc->isEnabled()) {
svc->fixedUpdate(dt); svc->fixedUpdate(dt);
@ -96,11 +105,12 @@ void SvcMgr::fixedUpdateAll(float dt) {
} }
bool SvcMgr::has(const char* name) const { bool SvcMgr::has(const char* name) const {
SvcMap::const_accessor acc; std::lock_guard<std::mutex> lock(svcMapMutex_);
return svcMap_.find(acc, name); return svcMap_.find(name) != svcMap_.end();
} }
size_t SvcMgr::count() const { size_t SvcMgr::count() const {
std::lock_guard<std::mutex> lock(svcMapMutex_);
return svcMap_.size(); return svcMap_.size();
} }

98
src/event/event_bus.cpp Normal file
View File

@ -0,0 +1,98 @@
#include <event/event_bus.h>
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

1
third_party/tbb vendored

@ -1 +0,0 @@
Subproject commit 492c01ee2b906e945f08355787dfc015dd7cc505

View File

@ -8,44 +8,11 @@ local function get_current_plat()
return get_config("plat") or os.host() return get_config("plat") or os.host()
end 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 引擎库目标 -- 定义 Extra2D 引擎库目标
function define_extra2d_engine() function define_extra2d_engine()
define_tbb_target()
target("extra2d") target("extra2d")
set_kind("static") set_kind("static")
add_deps("tbb")
add_files("src/**.cpp") add_files("src/**.cpp")
add_files("third_party/glad/src/glad.c") 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/glad/include", {public = true})
add_includedirs("third_party", {public = true}) add_includedirs("third_party", {public = true})
add_defines("TBB_USE_PROFILING_TOOLS=0")
local plat = get_current_plat() local plat = get_current_plat()
if plat == "mingw" then if plat == "mingw" then
add_defines("_UNICODE", "UNICODE") add_defines("_UNICODE", "UNICODE")