Skip to content

Commit 377f340

Browse files
authored
Fix #2060, make http request/respose reference counter thread-safe (#2064)
1 parent 687874c commit 377f340

File tree

5 files changed

+61
-16
lines changed

5 files changed

+61
-16
lines changed

core/base/Object.h

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -163,15 +163,38 @@ typedef void (Object::*SEL_CallFuncO)(Object*);
163163
typedef void (Object::*SEL_MenuHandler)(Object*);
164164
typedef void (Object::*SEL_SCHEDULE)(float);
165165

166-
#define AX_CALLFUNC_SELECTOR(_SELECTOR) static_cast<ax::SEL_CallFunc>(&_SELECTOR)
167-
#define AX_CALLFUNCN_SELECTOR(_SELECTOR) static_cast<ax::SEL_CallFuncN>(&_SELECTOR)
166+
#define AX_CALLFUNC_SELECTOR(_SELECTOR) static_cast<ax::SEL_CallFunc>(&_SELECTOR)
167+
#define AX_CALLFUNCN_SELECTOR(_SELECTOR) static_cast<ax::SEL_CallFuncN>(&_SELECTOR)
168168
#define AX_CALLFUNCND_SELECTOR(_SELECTOR) static_cast<ax::SEL_CallFuncND>(&_SELECTOR)
169-
#define AX_CALLFUNCO_SELECTOR(_SELECTOR) static_cast<ax::SEL_CallFuncO>(&_SELECTOR)
170-
#define AX_MENU_SELECTOR(_SELECTOR) static_cast<ax::SEL_MenuHandler>(&_SELECTOR)
171-
#define AX_SCHEDULE_SELECTOR(_SELECTOR) static_cast<ax::SEL_SCHEDULE>(&_SELECTOR)
169+
#define AX_CALLFUNCO_SELECTOR(_SELECTOR) static_cast<ax::SEL_CallFuncO>(&_SELECTOR)
170+
#define AX_MENU_SELECTOR(_SELECTOR) static_cast<ax::SEL_MenuHandler>(&_SELECTOR)
171+
#define AX_SCHEDULE_SELECTOR(_SELECTOR) static_cast<ax::SEL_SCHEDULE>(&_SELECTOR)
172172

173173
NS_AX_END
174174
// end of base group
175175
/** @} */
176176

177+
namespace axstd
178+
{
179+
template <typename _Ty, typename Enable = void>
180+
struct is_ref_counted : std::false_type
181+
{};
182+
183+
template <typename... _Types>
184+
struct is_ref_counted_helper
185+
{};
186+
187+
template <typename _Ty>
188+
struct is_ref_counted<_Ty,
189+
std::conditional_t<false,
190+
is_ref_counted_helper<decltype(std::declval<_Ty>().retain()),
191+
decltype(std::declval<_Ty>().release()),
192+
decltype(std::declval<_Ty>().getReferenceCount())>,
193+
void>> : public std::true_type
194+
{};
195+
196+
template <typename _Ty>
197+
inline constexpr bool is_ref_counted_v = is_ref_counted<std::remove_pointer_t<_Ty>>::value;
198+
} // namespace axstd
199+
177200
#endif // __BASE_CCREF_H__

core/base/RefPtr.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
Copyright (c) 2014 PlayFirst Inc.
33
Copyright (c) 2014-2016 Chukong Technologies Inc.
44
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
5+
Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md).
56
67
https://axmol.dev/
78
@@ -45,7 +46,7 @@ NS_AX_BEGIN
4546
{ \
4647
if (ptr) \
4748
{ \
48-
const_cast<Object*>(static_cast<const Object*>(ptr))->retain(); \
49+
(ptr)->retain(); \
4950
} \
5051
\
5152
} while (0);
@@ -56,7 +57,7 @@ NS_AX_BEGIN
5657
{ \
5758
if (ptr) \
5859
{ \
59-
const_cast<Object*>(static_cast<const Object*>(ptr))->release(); \
60+
(ptr)->release(); \
6061
} \
6162
\
6263
} while (0);
@@ -67,7 +68,7 @@ NS_AX_BEGIN
6768
{ \
6869
if (ptr) \
6970
{ \
70-
const_cast<Object*>(static_cast<const Object*>(ptr))->release(); \
71+
(ptr)->release(); \
7172
ptr = nullptr; \
7273
} \
7374
\
@@ -118,9 +119,9 @@ class RefPtr
118119
{
119120
if (other._ptr != _ptr)
120121
{
121-
AX_REF_PTR_SAFE_RETAIN(other._ptr);
122122
AX_REF_PTR_SAFE_RELEASE(_ptr);
123123
_ptr = other._ptr;
124+
AX_REF_PTR_SAFE_RETAIN(_ptr);
124125
}
125126

126127
return *this;
@@ -250,7 +251,7 @@ class RefPtr
250251
T* _ptr;
251252

252253
// NOTE: We can ensure T is derived from ax::Object at compile time here.
253-
static_assert(std::is_base_of<Object, typename std::remove_const<T>::type>::value, "T must be derived from Object");
254+
static_assert(axstd::is_ref_counted_v<typename std::remove_const<T>::type>, "T must be derived from Object");
254255
};
255256

256257
template <class T>

core/base/Vector.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ Copyright (c) 2010 ForzeField Studios S.L. http://forzefield.com
33
Copyright (c) 2010-2012 cocos2d-x.org
44
Copyright (c) 2013-2017 Chukong Technologies
55
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
6+
Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md).
67
78
https://axmol.dev/
89
@@ -110,7 +111,7 @@ class Vector
110111
/** Constructor. */
111112
Vector() : _data()
112113
{
113-
static_assert(std::is_convertible<T, Object*>::value, "Invalid Type for ax::Vector!");
114+
static_assert(axstd::is_ref_counted_v<T>, "Invalid Type for ax::Vector!");
114115
}
115116

116117
/**
@@ -119,7 +120,7 @@ class Vector
119120
*/
120121
explicit Vector(ssize_t capacity) : _data()
121122
{
122-
static_assert(std::is_convertible<T, Object*>::value, "Invalid Type for ax::Vector!");
123+
static_assert(axstd::is_ref_counted_v<T>, "Invalid Type for ax::Vector!");
123124
AXLOGV("In the default constructor with capacity of Vector.");
124125
reserve(capacity);
125126
}
@@ -143,7 +144,7 @@ class Vector
143144
/** Copy constructor. */
144145
Vector(const Vector& other)
145146
{
146-
static_assert(std::is_convertible<T, Object*>::value, "Invalid Type for ax::Vector!");
147+
static_assert(axstd::is_ref_counted_v<T>, "Invalid Type for ax::Vector!");
147148
AXLOGV("In the copy constructor!");
148149
_data = other._data;
149150
addRefForAllObjects();
@@ -152,7 +153,7 @@ class Vector
152153
/** Constructor with std::move semantic. */
153154
Vector(Vector&& other)
154155
{
155-
static_assert(std::is_convertible<T, Object*>::value, "Invalid Type for ax::Vector!");
156+
static_assert(axstd::is_ref_counted_v<T>, "Invalid Type for ax::Vector!");
156157
AXLOGV("In the move constructor of Vector!");
157158
_data = std::move(other._data);
158159
}

core/network/HttpRequest.h

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,26 @@ class HttpResponse;
5252

5353
typedef std::function<void(HttpClient* client, HttpResponse* response)> ccHttpRequestCallback;
5454

55+
class TSFRefCountedBase
56+
{
57+
public:
58+
TSFRefCountedBase() : _refCount(1) {}
59+
virtual ~TSFRefCountedBase() {}
60+
61+
void retain() { ++_refCount; }
62+
63+
void release()
64+
{
65+
if (--_refCount == 0)
66+
delete this;
67+
}
68+
69+
int getReferenceCount() const { return _refCount; }
70+
71+
protected:
72+
std::atomic_int _refCount;
73+
};
74+
5575
/**
5676
* Defines the object which users must packed for HttpClient::send(HttpRequest*) method.
5777
* Please refer to tests/test-cpp/Classes/ExtensionTest/NetworkTest/HttpClientTest.cpp as a sample
@@ -60,7 +80,7 @@ typedef std::function<void(HttpClient* client, HttpResponse* response)> ccHttpRe
6080
* @lua NA
6181
*/
6282

63-
class AX_DLL HttpRequest : public Object
83+
class AX_DLL HttpRequest : public TSFRefCountedBase
6484
{
6585
friend class HttpClient;
6686

core/network/HttpResponse.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ class HttpClient;
5151
* @since v2.0.2.
5252
* @lua NA
5353
*/
54-
class AX_DLL HttpResponse : public ax::Object
54+
class AX_DLL HttpResponse : public TSFRefCountedBase
5555
{
5656
friend class HttpClient;
5757

0 commit comments

Comments
 (0)