Skip to content

Commit 83a67af

Browse files
committed
Change subscriptions logic for CAI_Space
It's better to create callbacks in the same place where deletion happens. So, let's make template functions to automatically create callbacks and subscribe it.
1 parent 685e47d commit 83a67af

File tree

7 files changed

+71
-21
lines changed

7 files changed

+71
-21
lines changed

src/utils/xrSE_Factory/ai_space.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,13 @@ class CAI_Space
3434
EVENT_SCRIPT_ENGINE_RESET,
3535
EVENT_COUNT,
3636
};
37-
CEventNotifierCallback::CID Subscribe(CEventNotifierCallback* cb, EEventID event_id) { return 0; }
37+
38+
template <class CB, class... Args>
39+
CEventNotifierCallback::CID Subscribe(EEventID event_id, Args&&... args)
40+
{
41+
return 0;
42+
}
43+
3844
bool Unsubscribe(CEventNotifierCallback::CID cid, EEventID event_id) { return true; }
3945
};
4046

src/xrCore/Events/Notifier.h

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@ class CEventNotifierCallback
1616
virtual ~CEventNotifierCallback(){};
1717
};
1818

19+
class CEventNotifierCallbackWithCid : public CEventNotifierCallback
20+
{
21+
private:
22+
const CID m_cid;
23+
24+
public:
25+
CEventNotifierCallbackWithCid(CID cid) : m_cid(cid), CEventNotifierCallback(){};
26+
CID GetCid() const { return m_cid; }
27+
};
28+
1929
template <unsigned int CNT>
2030
class CEventNotifier
2131
{
@@ -41,6 +51,14 @@ class CEventNotifier
4151
xr_vector<CCallbackWrapper> m_callbacks;
4252
Lock m_lock;
4353

54+
CEventNotifierCallback::CID FindFreeCid()
55+
{
56+
ScopeLock lock(&m_lock);
57+
auto it = std::find(m_callbacks.begin(), m_callbacks.end(), nullptr);
58+
return (it == m_callbacks.end()) ? CEventNotifierCallback::INVALID_CID :
59+
std::distance(m_callbacks.begin(), it);
60+
}
61+
4462
public:
4563
CEventNotifierCallback::CID RegisterCallback(CEventNotifierCallback* cb)
4664
{
@@ -50,6 +68,28 @@ class CEventNotifier
5068
(it->callback.reset(cb), std::distance(m_callbacks.begin(), it));
5169
}
5270

71+
template <class CB, class... Args>
72+
CEventNotifierCallback::CID CreateRegisteredCallback(Args&&... args)
73+
{
74+
static_assert(std::is_base_of<CEventNotifierCallbackWithCid, CB>::value);
75+
76+
ScopeLock lock(&m_lock);
77+
78+
auto cid = FindFreeCid();
79+
CB* cb = new CB((cid == CEventNotifierCallback::INVALID_CID) ? m_callbacks.size() : cid, args...);
80+
81+
if (cid == CEventNotifierCallback::INVALID_CID)
82+
{
83+
m_callbacks.emplace_back(cb);
84+
}
85+
else
86+
{
87+
m_callbacks[cid].callback.reset(cb);
88+
}
89+
90+
return cb->GetCid();
91+
}
92+
5393
bool UnregisterCallback(CEventNotifierCallback::CID cid)
5494
{
5595
bool result = false;
@@ -100,6 +140,13 @@ class CEventNotifier
100140
return m_callbacks[event_id].RegisterCallback(cb);
101141
}
102142

143+
template <class CB, class... Args>
144+
CEventNotifierCallback::CID CreateRegisteredCallback(unsigned int event_id, Args&&... args)
145+
{
146+
R_ASSERT(event_id < CNT);
147+
return m_callbacks[event_id].CreateRegisteredCallback<CB>(args...);
148+
}
149+
103150
bool UnregisterCallback(CEventNotifierCallback::CID cid, unsigned int event_id)
104151
{
105152
R_ASSERT(event_id < CNT);

src/xrGame/MainMenu.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,16 +67,16 @@ CMainMenu* MainMenu() { return (CMainMenu*)g_pGamePersistent->m_pMainMenu; };
6767

6868
CMainMenu::CMainMenu()
6969
{
70-
class CResetEventCb : public CEventNotifierCallback
70+
class CResetEventCb : public CEventNotifierCallbackWithCid
7171
{
7272
CMainMenu* m_mainmenu;
7373

7474
public:
75-
CResetEventCb(CMainMenu* mm) : m_mainmenu(mm) {}
75+
CResetEventCb(CID cid, CMainMenu* mm) : m_mainmenu(mm), CEventNotifierCallbackWithCid(cid) {}
7676
void ProcessEvent() override { m_mainmenu->DestroyInternal(true); }
7777
};
7878

79-
m_script_reset_event_cid = ai().Subscribe(new CResetEventCb(this), CAI_Space::EVENT_SCRIPT_ENGINE_RESET);
79+
m_script_reset_event_cid = ai().Subscribe<CResetEventCb>(CAI_Space::EVENT_SCRIPT_ENGINE_RESET, this);
8080

8181
m_Flags.zero();
8282
m_startDialog = NULL;

src/xrGame/ai_space.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -197,11 +197,6 @@ void CAI_Space::set_alife(CALifeSimulator* alife_simulator)
197197
SetGameGraph(nullptr);
198198
}
199199

200-
CEventNotifierCallback::CID CAI_Space::Subscribe(CEventNotifierCallback* cb, EEventID event_id)
201-
{
202-
return m_events_notifier.RegisterCallback(cb, event_id);
203-
}
204-
205200
bool CAI_Space::Unsubscribe(CEventNotifierCallback::CID cid, EEventID event_id)
206201
{
207202
return m_events_notifier.UnregisterCallback(cid, event_id);

src/xrGame/ai_space.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,12 @@ class CAI_Space : public AISpaceBase
7373
virtual ~CAI_Space();
7474
static CAI_Space& GetInstance();
7575

76-
CEventNotifierCallback::CID Subscribe(CEventNotifierCallback* cb, EEventID event_id);
76+
template <class CB, class... Args>
77+
CEventNotifierCallback::CID Subscribe(EEventID event_id, Args&&... args)
78+
{
79+
return m_events_notifier.CreateRegisteredCallback<CB>(event_id, args...);
80+
}
81+
7782
bool Unsubscribe(CEventNotifierCallback::CID cid, EEventID event_id);
7883
void RestartScriptEngine();
7984

src/xrGame/ui/UIWpnParams.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -108,21 +108,19 @@ void CUIWpnParams::SetInfo(CInventoryItem* slot_wpn, CInventoryItem& cur_wpn)
108108
{
109109
if (!g_lua_wpn_params)
110110
{
111-
class CResetEventCb : public CEventNotifierCallback
111+
class CResetEventCb : public CEventNotifierCallbackWithCid
112112
{
113113
public:
114-
CID m_cid = INVALID_CID;
115-
114+
CResetEventCb(CID cid) : CEventNotifierCallbackWithCid(cid) {}
116115
void ProcessEvent() override
117116
{
118117
xr_delete(g_lua_wpn_params);
119-
ai().Unsubscribe(m_cid, CAI_Space::EVENT_SCRIPT_ENGINE_RESET);
118+
ai().Unsubscribe(GetCid(), CAI_Space::EVENT_SCRIPT_ENGINE_RESET);
120119
}
121120
};
122121

123122
g_lua_wpn_params = new SLuaWpnParams();
124-
auto cb = new CResetEventCb();
125-
cb->m_cid = ai().Subscribe(cb, CAI_Space::EVENT_SCRIPT_ENGINE_RESET);
123+
ai().Subscribe<CResetEventCb>(CAI_Space::EVENT_SCRIPT_ENGINE_RESET);
126124
}
127125

128126
LPCSTR cur_section = cur_wpn.object().cNameSect().c_str();

src/xrServerEntities/object_factory_inline.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,19 @@ IC const CObjectFactory& object_factory()
1818
g_object_factory = new CObjectFactory();
1919
g_object_factory->init();
2020

21-
class CResetEventCb : public CEventNotifierCallback
21+
class CResetEventCb : public CEventNotifierCallbackWithCid
2222
{
2323
public:
24-
CID m_cid;
24+
CResetEventCb(CID cid) : CEventNotifierCallbackWithCid(cid) {}
2525

2626
void ProcessEvent() override
2727
{
2828
xr_delete(g_object_factory);
29-
ai().Unsubscribe(m_cid, CAI_Space::EVENT_SCRIPT_ENGINE_RESET);
29+
ai().Unsubscribe(GetCid(), CAI_Space::EVENT_SCRIPT_ENGINE_RESET);
3030
}
3131
};
3232

33-
CResetEventCb* e = new CResetEventCb();
34-
e->m_cid = ai().Subscribe(e, CAI_Space::EVENT_SCRIPT_ENGINE_RESET);
33+
ai().Subscribe<CResetEventCb>(CAI_Space::EVENT_SCRIPT_ENGINE_RESET);
3534
}
3635
return (*g_object_factory);
3736
}

0 commit comments

Comments
 (0)