refactor(core): 移除TBB依赖并重构事件系统和调度器
重构服务管理器和调度器,使用标准库替代TBB并发容器 将事件系统从core移动到独立event目录并优化实现 更新构建脚本移除TBB相关配置 添加线程安全队列实现并行调度
This commit is contained in:
parent
0761b55864
commit
5a3d0cd9de
|
|
@ -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); } \
|
||||
};
|
||||
|
|
@ -4,12 +4,11 @@
|
|||
#include <types/ptr/ref_counted.h>
|
||||
#include <types/ptr/intrusive_ptr.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 <vector>
|
||||
#include <unordered_map>
|
||||
#include <queue>
|
||||
#include <mutex>
|
||||
|
||||
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<UpdateEntry> queue_;
|
||||
};
|
||||
|
||||
std::vector<UpdateEntry> updates_;
|
||||
tbb::concurrent_hash_map<TimerTarget*, size_t> updateIndex_;
|
||||
tbb::concurrent_hash_map<TimerHdl, Ptr<Timer>> timers_;
|
||||
tbb::concurrent_priority_queue<UpdateEntry> updateQueue_;
|
||||
std::unordered_map<TimerTarget*, size_t> updateIndex_;
|
||||
mutable std::mutex updateIndexMutex_;
|
||||
|
||||
std::unordered_map<TimerHdl, Ptr<Timer>> timers_;
|
||||
mutable std::mutex timersMutex_;
|
||||
|
||||
SafePriorityQueue updateQueue_;
|
||||
|
||||
std::atomic<TimerHdl> nextHdl_{1};
|
||||
std::atomic<float> timeScale_{1.0f};
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@
|
|||
#include <types/const/priority.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <tbb/concurrent_hash_map.h>
|
||||
#include <unordered_map>
|
||||
#include <mutex>
|
||||
|
||||
namespace extra2d {
|
||||
|
||||
|
|
@ -88,8 +89,10 @@ public:
|
|||
private:
|
||||
SvcMgr() = default;
|
||||
|
||||
using SvcMap = tbb::concurrent_hash_map<std::string, Ptr<IService>>;
|
||||
using SvcMap = std::unordered_map<std::string, Ptr<IService>>;
|
||||
SvcMap svcMap_;
|
||||
mutable std::mutex svcMapMutex_;
|
||||
|
||||
std::vector<Ptr<IService>> sortedSvcs_;
|
||||
|
||||
void sortSvcs();
|
||||
|
|
|
|||
|
|
@ -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); \
|
||||
} \
|
||||
};
|
||||
|
|
@ -1,8 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include <core/event/event_bus_macros.h>
|
||||
#include <types/base/types.h>
|
||||
#include <event/event_bus_macros.h>
|
||||
#include <platform/input.h>
|
||||
#include <types/base/types.h>
|
||||
|
||||
|
||||
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 &)
|
||||
|
||||
// ============================================================================
|
||||
// 场景事件
|
||||
|
|
@ -23,10 +23,15 @@
|
|||
#include <core/service.h>
|
||||
|
||||
// Platform
|
||||
#include <platform/sdl2.h>
|
||||
#include <platform/input.h>
|
||||
#include <platform/window.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
|
||||
#include <utils/logger.h>
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
#include <app/application.h>
|
||||
#include <core/director.h>
|
||||
#include <core/event/events.h>
|
||||
#include <core/service.h>
|
||||
#include <event/events.h>
|
||||
#include <platform/file.h>
|
||||
#include <platform/input.h>
|
||||
#include <platform/sdl2.h>
|
||||
#include <platform/window.h>
|
||||
#include <utils/logger.h>
|
||||
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
#include <core/scheduler.h>
|
||||
#include <algorithm>
|
||||
#include <thread>
|
||||
#include <future>
|
||||
|
||||
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() {
|
||||
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<std::mutex> 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<TimerTarget*, size_t>::accessor acc;
|
||||
if (updateIndex_.find(acc, target)) {
|
||||
size_t idx = acc->second;
|
||||
std::lock_guard<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> lock(timersMutex_);
|
||||
timers_.erase(hdl);
|
||||
}
|
||||
|
||||
void Scheduler::unscheduleAll() {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(timersMutex_);
|
||||
timers_.clear();
|
||||
}
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(updateIndexMutex_);
|
||||
updates_.clear();
|
||||
updateIndex_.clear();
|
||||
}
|
||||
updateQueue_.clear();
|
||||
}
|
||||
|
||||
void Scheduler::pause(TimerHdl hdl) {
|
||||
tbb::concurrent_hash_map<TimerHdl, Ptr<Timer>>::accessor acc;
|
||||
if (timers_.find(acc, hdl)) {
|
||||
acc->second->pause();
|
||||
std::lock_guard<std::mutex> lock(timersMutex_);
|
||||
auto it = timers_.find(hdl);
|
||||
if (it != timers_.end()) {
|
||||
it->second->pause();
|
||||
}
|
||||
}
|
||||
|
||||
void Scheduler::resume(TimerHdl hdl) {
|
||||
tbb::concurrent_hash_map<TimerHdl, Ptr<Timer>>::accessor acc;
|
||||
if (timers_.find(acc, hdl)) {
|
||||
acc->second->resume();
|
||||
std::lock_guard<std::mutex> lock(timersMutex_);
|
||||
auto it = timers_.find(hdl);
|
||||
if (it != timers_.end()) {
|
||||
it->second->resume();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -159,6 +208,9 @@ void Scheduler::update(float dt) {
|
|||
|
||||
locked_ = true;
|
||||
|
||||
// 更新所有 update 回调
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(updateIndexMutex_);
|
||||
for (auto& entry : updates_) {
|
||||
if (!entry.markedForDel && !entry.paused && entry.target) {
|
||||
entry.target->update(scaledDt);
|
||||
|
|
@ -170,8 +222,12 @@ void Scheduler::update(float dt) {
|
|||
[](const UpdateEntry& e) { return e.markedForDel; }),
|
||||
updates_.end()
|
||||
);
|
||||
}
|
||||
|
||||
// 更新定时器
|
||||
std::vector<TimerHdl> toRemove;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(timersMutex_);
|
||||
for (auto it = timers_.begin(); it != timers_.end(); ++it) {
|
||||
auto& timer = it->second;
|
||||
timer->update(scaledDt);
|
||||
|
|
@ -183,6 +239,7 @@ void Scheduler::update(float dt) {
|
|||
for (auto hdl : toRemove) {
|
||||
timers_.erase(hdl);
|
||||
}
|
||||
}
|
||||
|
||||
locked_ = false;
|
||||
}
|
||||
|
|
@ -192,23 +249,46 @@ void Scheduler::updateParallel(float dt) {
|
|||
|
||||
locked_ = true;
|
||||
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, updates_.size()),
|
||||
[this, scaledDt](const tbb::blocked_range<size_t>& range) {
|
||||
for (size_t i = range.begin(); i != range.end(); ++i) {
|
||||
// 并行更新所有 update 回调(使用标准库线程)
|
||||
{
|
||||
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];
|
||||
if (!entry.markedForDel && !entry.paused && entry.target) {
|
||||
entry.target->update(scaledDt);
|
||||
}
|
||||
}
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
for (auto& f : futures) {
|
||||
f.wait();
|
||||
}
|
||||
|
||||
updates_.erase(
|
||||
std::remove_if(updates_.begin(), updates_.end(),
|
||||
[](const UpdateEntry& e) { return e.markedForDel; }),
|
||||
updates_.end()
|
||||
);
|
||||
}
|
||||
|
||||
// 更新定时器
|
||||
std::vector<TimerHdl> toRemove;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(timersMutex_);
|
||||
for (auto it = timers_.begin(); it != timers_.end(); ++it) {
|
||||
auto& timer = it->second;
|
||||
timer->update(scaledDt);
|
||||
|
|
@ -220,16 +300,18 @@ void Scheduler::updateParallel(float dt) {
|
|||
for (auto hdl : toRemove) {
|
||||
timers_.erase(hdl);
|
||||
}
|
||||
}
|
||||
|
||||
locked_ = false;
|
||||
}
|
||||
|
||||
bool Scheduler::isScheduled(TimerHdl hdl) const {
|
||||
tbb::concurrent_hash_map<TimerHdl, Ptr<Timer>>::const_accessor acc;
|
||||
return timers_.find(acc, hdl);
|
||||
std::lock_guard<std::mutex> lock(timersMutex_);
|
||||
return timers_.find(hdl) != timers_.end();
|
||||
}
|
||||
|
||||
size_t Scheduler::count() const {
|
||||
std::lock_guard<std::mutex> lock(timersMutex_);
|
||||
return timers_.size();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<IService>(svc);
|
||||
|
||||
std::lock_guard<std::mutex> lock(svcMapMutex_);
|
||||
svcMap_[svc->name()] = Ptr<IService>(svc);
|
||||
sortSvcs();
|
||||
}
|
||||
|
||||
void SvcMgr::unreg(const char* name) {
|
||||
std::lock_guard<std::mutex> lock(svcMapMutex_);
|
||||
svcMap_.erase(name);
|
||||
sortSvcs();
|
||||
}
|
||||
|
||||
Ptr<IService> SvcMgr::get(const char* name) {
|
||||
SvcMap::const_accessor acc;
|
||||
if (svcMap_.find(acc, name)) {
|
||||
return acc->second;
|
||||
std::lock_guard<std::mutex> lock(svcMapMutex_);
|
||||
auto it = svcMap_.find(name);
|
||||
if (it != svcMap_.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool SvcMgr::initAll() {
|
||||
std::lock_guard<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> lock(svcMapMutex_);
|
||||
return svcMap_.find(name) != svcMap_.end();
|
||||
}
|
||||
|
||||
size_t SvcMgr::count() const {
|
||||
std::lock_guard<std::mutex> lock(svcMapMutex_);
|
||||
return svcMap_.size();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 +0,0 @@
|
|||
Subproject commit 492c01ee2b906e945f08355787dfc015dd7cc505
|
||||
|
|
@ -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")
|
||||
|
|
|
|||
Loading…
Reference in New Issue