Skip to content

Commit 9587ce3

Browse files
committed
fix weakref leaking if strong references outlive all weak references
1 parent c3b4e3d commit 9587ce3

File tree

2 files changed

+30
-10
lines changed

2 files changed

+30
-10
lines changed

loader/include/Geode/utils/cocos.hpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,8 +363,14 @@ namespace geode {
363363

364364
void check(cocos2d::CCObject* obj);
365365

366+
// Releases the object from the pool, removing the strong reference to it
367+
void forget(cocos2d::CCObject* obj);
368+
366369
friend class WeakRefController;
367370

371+
template <class T>
372+
friend class WeakRef;
373+
368374
public:
369375
static WeakRefPool* get();
370376

@@ -429,6 +435,11 @@ namespace geode {
429435
// If the WeakRef is moved, m_controller is null
430436
if (m_controller) {
431437
m_controller->isManaged();
438+
439+
if (m_controller.use_count() == 2) {
440+
// if refcount is 2 (this WeakRef + pool), free the object to avoid leaks
441+
WeakRefPool::get()->forget(m_controller->get());
442+
}
432443
}
433444
}
434445

loader/src/utils/cocos.cpp

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -277,16 +277,25 @@ WeakRefPool* WeakRefPool::get() {
277277
void WeakRefPool::check(CCObject* obj) {
278278
// if this object's only reference is the WeakRefPool aka only weak
279279
// references exist to it, then release it
280-
if (obj && m_pool.contains(obj) && obj->retainCount() == 1) {
281-
// set delegates to null because those aren't retained!
282-
if (auto input = typeinfo_cast<CCTextInputNode*>(obj)) {
283-
input->m_delegate = nullptr;
284-
}
285-
obj->release();
286-
// log::info("nullify {}", m_pool.at(obj).get());
287-
m_pool.at(obj)->m_obj = nullptr;
288-
m_pool.erase(obj);
280+
if (obj && obj->retainCount() == 1) {
281+
this->forget(obj);
282+
}
283+
}
284+
285+
void WeakRefPool::forget(CCObject* obj) {
286+
if (!obj || !m_pool.contains(obj)) {
287+
return;
289288
}
289+
290+
// set delegates to null because those aren't retained!
291+
if (auto input = typeinfo_cast<CCTextInputNode*>(obj)) {
292+
input->m_delegate = nullptr;
293+
}
294+
295+
obj->release();
296+
// log::info("nullify {}", m_pool.at(obj).get());
297+
m_pool.at(obj)->m_obj = nullptr;
298+
m_pool.erase(obj);
290299
}
291300

292301
std::shared_ptr<WeakRefController> WeakRefPool::manage(CCObject* obj) {
@@ -295,7 +304,7 @@ std::shared_ptr<WeakRefController> WeakRefPool::manage(CCObject* obj) {
295304
}
296305

297306
if (!m_pool.contains(obj)) {
298-
CC_SAFE_RETAIN(obj);
307+
obj->retain();
299308
auto controller = std::make_shared<WeakRefController>();
300309
controller->m_obj = obj;
301310
m_pool.insert({ obj, controller });

0 commit comments

Comments
 (0)