Skip to content

Commit 481c457

Browse files
authored
Allow using const reference counted object ptrs (#28)
1 parent 9da4c9b commit 481c457

File tree

2 files changed

+236
-8
lines changed

2 files changed

+236
-8
lines changed

modules/juce_core/memory/juce_ReferenceCountedObject.h

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -88,15 +88,15 @@ class JUCE_API ReferenceCountedObject
8888
This is done automatically by the smart pointer, but is public just
8989
in case it's needed for nefarious purposes.
9090
*/
91-
void incReferenceCount() noexcept
91+
void incReferenceCount() const noexcept
9292
{
9393
++refCount;
9494
}
9595

9696
/** Decreases the object's reference count.
9797
If the count gets to zero, the object will be deleted.
9898
*/
99-
void decReferenceCount() noexcept
99+
void decReferenceCount() const noexcept
100100
{
101101
jassert (getReferenceCount() > 0);
102102

@@ -108,7 +108,7 @@ class JUCE_API ReferenceCountedObject
108108
If the count gets to zero, the object will not be deleted, but this method
109109
will return true, allowing the caller to take care of deletion.
110110
*/
111-
bool decReferenceCountWithoutDeleting() noexcept
111+
bool decReferenceCountWithoutDeleting() const noexcept
112112
{
113113
jassert (getReferenceCount() > 0);
114114
return --refCount == 0;
@@ -151,7 +151,8 @@ class JUCE_API ReferenceCountedObject
151151

152152
private:
153153
//==============================================================================
154-
Atomic<int> refCount { 0 };
154+
mutable Atomic<int> refCount { 0 };
155+
155156
friend struct ContainerDeletePolicy<ReferenceCountedObject>;
156157
};
157158

@@ -177,15 +178,15 @@ class JUCE_API SingleThreadedReferenceCountedObject
177178
This is done automatically by the smart pointer, but is public just
178179
in case it's needed for nefarious purposes.
179180
*/
180-
void incReferenceCount() noexcept
181+
void incReferenceCount() const noexcept
181182
{
182183
++refCount;
183184
}
184185

185186
/** Decreases the object's reference count.
186187
If the count gets to zero, the object will be deleted.
187188
*/
188-
void decReferenceCount() noexcept
189+
void decReferenceCount() const noexcept
189190
{
190191
jassert (getReferenceCount() > 0);
191192

@@ -197,7 +198,7 @@ class JUCE_API SingleThreadedReferenceCountedObject
197198
If the count gets to zero, the object will not be deleted, but this method
198199
will return true, allowing the caller to take care of deletion.
199200
*/
200-
bool decReferenceCountWithoutDeleting() noexcept
201+
bool decReferenceCountWithoutDeleting() const noexcept
201202
{
202203
jassert (getReferenceCount() > 0);
203204
return --refCount == 0;
@@ -232,7 +233,8 @@ class JUCE_API SingleThreadedReferenceCountedObject
232233

233234
private:
234235
//==============================================================================
235-
int refCount = 0;
236+
mutable int refCount = 0;
237+
236238
friend struct ContainerDeletePolicy<ReferenceCountedObject>;
237239
};
238240

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
/*
2+
==============================================================================
3+
This file is part of the YUP library.
4+
Copyright (c) 2024 - [email protected]
5+
YUP is an open source library subject to open-source licensing.
6+
The code included in this file is provided under the terms of the ISC license
7+
http://www.isc.org/downloads/software-support-policy/isc-license. Permission
8+
to use, copy, modify, and/or distribute this software for any purpose with or
9+
without fee is hereby granted provided that the above copyright notice and
10+
this permission notice appear in all copies.
11+
YUP IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
12+
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
13+
DISCLAIMED.
14+
==============================================================================
15+
*/
16+
17+
#include <gtest/gtest.h>
18+
19+
#include <juce_core/juce_core.h>
20+
21+
using namespace juce;
22+
23+
class TestClass : public ReferenceCountedObject
24+
{
25+
public:
26+
using Ptr = ReferenceCountedObjectPtr<TestClass>;
27+
using ConstPtr = ReferenceCountedObjectPtr<const TestClass>;
28+
29+
void doSomething() const {}
30+
};
31+
32+
class SingleThreadedTestClass : public SingleThreadedReferenceCountedObject
33+
{
34+
public:
35+
using Ptr = ReferenceCountedObjectPtr<SingleThreadedTestClass>;
36+
using ConstPtr = ReferenceCountedObjectPtr<const SingleThreadedTestClass>;
37+
38+
void doSomething() const {}
39+
};
40+
41+
TEST (ReferenceCountedObjectTests, IncDecReferenceCount)
42+
{
43+
TestClass::Ptr obj = new TestClass();
44+
EXPECT_EQ (obj->getReferenceCount(), 1);
45+
46+
obj->incReferenceCount();
47+
EXPECT_EQ (obj->getReferenceCount(), 2);
48+
49+
obj->decReferenceCount();
50+
EXPECT_EQ (obj->getReferenceCount(), 1);
51+
52+
obj = nullptr; // this should decrement the count and delete the object
53+
}
54+
55+
TEST (ReferenceCountedObjectTests, IncDecConstReferenceCount)
56+
{
57+
TestClass::ConstPtr obj = new TestClass();
58+
EXPECT_EQ (obj->getReferenceCount(), 1);
59+
60+
obj->incReferenceCount();
61+
EXPECT_EQ (obj->getReferenceCount(), 2);
62+
63+
obj->decReferenceCount();
64+
EXPECT_EQ (obj->getReferenceCount(), 1);
65+
66+
obj = nullptr; // this should decrement the count and delete the object
67+
}
68+
69+
TEST (ReferenceCountedObjectTests, DecReferenceCountWithoutDeleting)
70+
{
71+
TestClass::Ptr obj = new TestClass();
72+
EXPECT_EQ (obj->getReferenceCount(), 1);
73+
74+
EXPECT_TRUE (obj->decReferenceCountWithoutDeleting());
75+
EXPECT_EQ (obj->getReferenceCount(), 0);
76+
77+
delete obj;
78+
}
79+
80+
TEST (ReferenceCountedObjectTests, DecConstReferenceCountWithoutDeleting)
81+
{
82+
TestClass::ConstPtr obj = new TestClass();
83+
EXPECT_EQ (obj->getReferenceCount(), 1);
84+
85+
EXPECT_TRUE (obj->decReferenceCountWithoutDeleting());
86+
EXPECT_EQ (obj->getReferenceCount(), 0);
87+
88+
delete obj;
89+
}
90+
91+
// SingleThreadedReferenceCountedObject tests
92+
TEST (SingleThreadedReferenceCountedObjectTests, IncDecReferenceCount)
93+
{
94+
SingleThreadedTestClass::Ptr obj = new SingleThreadedTestClass();
95+
EXPECT_EQ (obj->getReferenceCount(), 1);
96+
97+
obj->incReferenceCount();
98+
EXPECT_EQ (obj->getReferenceCount(), 2);
99+
100+
obj->decReferenceCount();
101+
EXPECT_EQ (obj->getReferenceCount(), 1);
102+
103+
obj = nullptr; // this should decrement the count and delete the object
104+
}
105+
106+
TEST (SingleThreadedReferenceCountedObjectTests, IncDecConstReferenceCount)
107+
{
108+
SingleThreadedTestClass::ConstPtr obj = new SingleThreadedTestClass();
109+
EXPECT_EQ (obj->getReferenceCount(), 1);
110+
111+
obj->incReferenceCount();
112+
EXPECT_EQ (obj->getReferenceCount(), 2);
113+
114+
obj->decReferenceCount();
115+
EXPECT_EQ (obj->getReferenceCount(), 1);
116+
117+
obj = nullptr; // this should decrement the count and delete the object
118+
}
119+
120+
TEST (SingleThreadedReferenceCountedObjectTests, DecReferenceCountWithoutDeleting)
121+
{
122+
SingleThreadedTestClass::Ptr obj = new SingleThreadedTestClass();
123+
EXPECT_EQ (obj->getReferenceCount(), 1);
124+
125+
EXPECT_TRUE (obj->decReferenceCountWithoutDeleting());
126+
EXPECT_EQ (obj->getReferenceCount(), 0);
127+
128+
delete obj;
129+
}
130+
131+
TEST (SingleThreadedReferenceCountedObjectTests, DecConstReferenceCountWithoutDeleting)
132+
{
133+
SingleThreadedTestClass::ConstPtr obj = new SingleThreadedTestClass();
134+
EXPECT_EQ (obj->getReferenceCount(), 1);
135+
136+
EXPECT_TRUE (obj->decReferenceCountWithoutDeleting());
137+
EXPECT_EQ (obj->getReferenceCount(), 0);
138+
139+
delete obj;
140+
}
141+
142+
// ReferenceCountedObjectPtr tests
143+
TEST (ReferenceCountedObjectPtrTests, PointerAssignment)
144+
{
145+
TestClass::Ptr obj1 = new TestClass();
146+
TestClass::Ptr obj2 = obj1;
147+
148+
EXPECT_EQ (obj1->getReferenceCount(), 2);
149+
EXPECT_EQ (obj2->getReferenceCount(), 2);
150+
151+
obj1 = nullptr;
152+
EXPECT_EQ (obj2->getReferenceCount(), 1);
153+
obj2 = nullptr; // this should delete the object
154+
}
155+
156+
TEST (ReferenceCountedObjectPtrTests, PointerComparison)
157+
{
158+
TestClass::Ptr obj1 = new TestClass();
159+
TestClass::Ptr obj2 = obj1;
160+
161+
EXPECT_EQ (obj1, obj2);
162+
EXPECT_NE (obj1, nullptr);
163+
164+
obj1 = nullptr;
165+
EXPECT_EQ (obj1, nullptr);
166+
EXPECT_NE (obj2, nullptr);
167+
}
168+
169+
TEST (ReferenceCountedObjectPtrTests, PointerDereference)
170+
{
171+
TestClass::Ptr obj = new TestClass();
172+
EXPECT_NO_THROW (obj->doSomething());
173+
EXPECT_NO_THROW (*obj);
174+
}
175+
176+
TEST (ReferenceCountedObjectPtrTests, Reset)
177+
{
178+
TestClass::Ptr obj = new TestClass();
179+
EXPECT_EQ (obj->getReferenceCount(), 1);
180+
181+
obj.reset();
182+
EXPECT_EQ (obj, nullptr);
183+
}
184+
185+
// SingleThreadedReferenceCountedObjectPtr tests
186+
TEST (SingleThreadedReferenceCountedObjectPtrTests, PointerAssignment)
187+
{
188+
SingleThreadedTestClass::Ptr obj1 = new SingleThreadedTestClass();
189+
SingleThreadedTestClass::Ptr obj2 = obj1;
190+
191+
EXPECT_EQ (obj1->getReferenceCount(), 2);
192+
EXPECT_EQ (obj2->getReferenceCount(), 2);
193+
194+
obj1 = nullptr;
195+
EXPECT_EQ (obj2->getReferenceCount(), 1);
196+
obj2 = nullptr; // this should delete the object
197+
}
198+
199+
TEST (SingleThreadedReferenceCountedObjectPtrTests, PointerComparison)
200+
{
201+
SingleThreadedTestClass::Ptr obj1 = new SingleThreadedTestClass();
202+
SingleThreadedTestClass::Ptr obj2 = obj1;
203+
204+
EXPECT_EQ (obj1, obj2);
205+
EXPECT_NE (obj1, nullptr);
206+
207+
obj1 = nullptr;
208+
EXPECT_EQ (obj1, nullptr);
209+
EXPECT_NE (obj2, nullptr);
210+
}
211+
212+
TEST (SingleThreadedReferenceCountedObjectPtrTests, PointerDereference)
213+
{
214+
SingleThreadedTestClass::Ptr obj = new SingleThreadedTestClass();
215+
EXPECT_NO_THROW (obj->doSomething());
216+
EXPECT_NO_THROW (*obj);
217+
}
218+
219+
TEST (SingleThreadedReferenceCountedObjectPtrTests, Reset)
220+
{
221+
SingleThreadedTestClass::Ptr obj = new SingleThreadedTestClass();
222+
EXPECT_EQ (obj->getReferenceCount(), 1);
223+
224+
obj.reset();
225+
EXPECT_EQ (obj, nullptr);
226+
}

0 commit comments

Comments
 (0)