xref: /aosp_15_r20/external/deqp/framework/delibs/decpp/deSharedPtr.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements C++ Base Library
3  * -----------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Shared pointer.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "deSharedPtr.hpp"
25 #include "deThread.hpp"
26 #include "deClock.h"
27 
28 #include <exception>
29 
30 namespace de
31 {
32 
33 namespace
34 {
35 
36 enum
37 {
38     THREAD_TEST_TIME = 200 * 1000
39 };
40 
41 class Object
42 {
43 public:
Object(bool & exists)44     Object(bool &exists) : m_exists(exists)
45     {
46         m_exists = true;
47     }
48 
~Object(void)49     virtual ~Object(void)
50     {
51         m_exists = false;
52     }
53 
54 private:
55     bool &m_exists;
56 };
57 
58 class DerivedObject : public Object
59 {
60 public:
DerivedObject(bool & exists)61     DerivedObject(bool &exists) : Object(exists)
62     {
63     }
64 };
65 
66 class SharedPtrTestThread : public Thread
67 {
68 public:
SharedPtrTestThread(const SharedPtr<Object> & ptr,const bool & exists)69     SharedPtrTestThread(const SharedPtr<Object> &ptr, const bool &exists) : m_ptr(ptr), m_exists(exists)
70     {
71     }
72 
run(void)73     void run(void)
74     {
75         uint64_t startTime = deGetMicroseconds();
76         uint64_t cnt       = 0;
77 
78         for (;; cnt++)
79         {
80             if (((cnt & (1 << 14)) != 0) && (deGetMicroseconds() - startTime >= THREAD_TEST_TIME))
81                 break;
82 
83             {
84                 SharedPtr<Object> ptrA(m_ptr);
85                 {
86                     SharedPtr<Object> ptrB;
87                     ptrB = ptrA;
88                     ptrA = SharedPtr<Object>();
89                 }
90             }
91             DE_TEST_ASSERT(m_exists);
92         }
93     }
94 
95 private:
96     SharedPtr<Object> m_ptr;
97     const bool &m_exists;
98 };
99 
100 class WeakPtrTestThread : public Thread
101 {
102 public:
WeakPtrTestThread(const SharedPtr<Object> & ptr,const bool & exists)103     WeakPtrTestThread(const SharedPtr<Object> &ptr, const bool &exists) : m_ptr(ptr), m_exists(exists)
104     {
105     }
106 
run(void)107     void run(void)
108     {
109         uint64_t startTime = deGetMicroseconds();
110         uint64_t cnt       = 0;
111 
112         for (;; cnt++)
113         {
114             if (((cnt & (1 << 14)) != 0) && (deGetMicroseconds() - startTime >= THREAD_TEST_TIME))
115                 break;
116 
117             {
118                 WeakPtr<Object> ptrA(m_ptr);
119                 {
120                     WeakPtr<Object> ptrB;
121                     ptrB = ptrA;
122                     ptrA = SharedPtr<Object>();
123                 }
124             }
125             DE_TEST_ASSERT(m_exists);
126         }
127     }
128 
129 private:
130     SharedPtr<Object> m_ptr;
131     const bool &m_exists;
132 };
133 
makeObject(bool & exists)134 SharedPtr<Object> makeObject(bool &exists)
135 {
136     return SharedPtr<Object>(new Object(exists));
137 }
138 
139 struct CustomDeleter
140 {
CustomDeleterde::__anon7181c7410111::CustomDeleter141     CustomDeleter(bool *called) : m_called(called)
142     {
143     }
144 
operator ()de::__anon7181c7410111::CustomDeleter145     void operator()(Object *ptr)
146     {
147         DE_TEST_ASSERT(!*m_called);
148         delete ptr;
149         *m_called = true;
150     }
151 
152     bool *m_called;
153 };
154 
155 } // namespace
156 
SharedPtr_selfTest(void)157 void SharedPtr_selfTest(void)
158 {
159     // Empty pointer test.
160     {
161         SharedPtr<Object> ptr;
162         DE_TEST_ASSERT(ptr.get() == DE_NULL);
163         DE_TEST_ASSERT(!ptr);
164     }
165 
166     // Empty pointer copy.
167     {
168         SharedPtr<Object> ptrA;
169         SharedPtr<Object> ptrB(ptrA);
170         DE_TEST_ASSERT(ptrB.get() == DE_NULL);
171     }
172 
173     // Empty pointer assignment.
174     {
175         SharedPtr<Object> ptrA;
176         SharedPtr<Object> ptrB;
177         ptrB = ptrA;
178         ptrB = *&ptrB;
179     }
180 
181     // Basic test.
182     {
183         bool exists = false;
184         {
185             SharedPtr<Object> ptr(new Object(exists));
186             DE_TEST_ASSERT(exists);
187             DE_TEST_ASSERT(ptr.get() != DE_NULL);
188             DE_TEST_ASSERT(ptr);
189         }
190         DE_TEST_ASSERT(!exists);
191     }
192 
193     // Exception test.
194     {
195         bool exists = false;
196         try
197         {
198             SharedPtr<Object> ptr(new Object(exists));
199             DE_TEST_ASSERT(exists);
200             DE_TEST_ASSERT(ptr.get() != DE_NULL);
201             throw std::exception();
202         }
203         catch (const std::exception &)
204         {
205             DE_TEST_ASSERT(!exists);
206         }
207         DE_TEST_ASSERT(!exists);
208     }
209 
210     // Expression test.
211     {
212         bool exists = false;
213         bool test   = (SharedPtr<Object>(new Object(exists))).get() != DE_NULL && exists;
214         DE_TEST_ASSERT(!exists);
215         DE_TEST_ASSERT(test);
216     }
217 
218     // Assignment test.
219     {
220         bool exists = false;
221         SharedPtr<Object> ptr(new Object(exists));
222         DE_TEST_ASSERT(exists);
223         ptr = SharedPtr<Object>();
224         DE_TEST_ASSERT(!exists);
225     }
226 
227     // Self-assignment test.
228     {
229         bool exists = false;
230         {
231             SharedPtr<Object> ptr(new Object(exists));
232             DE_TEST_ASSERT(exists);
233             DE_TEST_ASSERT(ptr.get() != DE_NULL);
234             ptr = *&ptr;
235         }
236         DE_TEST_ASSERT(!exists);
237     }
238 
239     // Basic multi-reference via copy ctor.
240     {
241         bool exists = false;
242         {
243             SharedPtr<Object> ptrA(new Object(exists));
244             DE_TEST_ASSERT(exists);
245             {
246                 SharedPtr<Object> ptrB(ptrA);
247                 DE_TEST_ASSERT(exists);
248             }
249             DE_TEST_ASSERT(exists);
250         }
251         DE_TEST_ASSERT(!exists);
252     }
253 
254     // Basic multi-reference via assignment to empty.
255     {
256         bool exists = false;
257         {
258             SharedPtr<Object> ptrA(new Object(exists));
259             DE_TEST_ASSERT(exists);
260             {
261                 SharedPtr<Object> ptrB;
262                 ptrB = ptrA;
263                 DE_TEST_ASSERT(exists);
264             }
265             DE_TEST_ASSERT(exists);
266         }
267         DE_TEST_ASSERT(!exists);
268     }
269 
270     // Multi-reference via assignment to non-empty.
271     {
272         bool existsA = false;
273         bool existsB = false;
274         {
275             SharedPtr<Object> ptrA(new Object(existsA));
276             DE_TEST_ASSERT(existsA);
277             {
278                 SharedPtr<Object> ptrB(new Object(existsB));
279                 DE_TEST_ASSERT(existsB);
280                 ptrA = ptrB;
281                 DE_TEST_ASSERT(!existsA);
282                 DE_TEST_ASSERT(existsB);
283             }
284             DE_TEST_ASSERT(existsB);
285         }
286         DE_TEST_ASSERT(!existsB);
287     }
288 
289     // Return from function.
290     {
291         bool exists = false;
292         {
293             SharedPtr<Object> ptr;
294             ptr = makeObject(exists);
295             DE_TEST_ASSERT(exists);
296         }
297         DE_TEST_ASSERT(!exists);
298     }
299 
300     // Equality comparison.
301     {
302         bool existsA = false;
303         bool existsB = false;
304         SharedPtr<Object> ptrA(new Object(existsA));
305         SharedPtr<Object> ptrB(new Object(existsB));
306         SharedPtr<Object> ptrC(ptrA);
307 
308         DE_TEST_ASSERT(ptrA == ptrA);
309         DE_TEST_ASSERT(ptrA != ptrB);
310         DE_TEST_ASSERT(ptrA == ptrC);
311         DE_TEST_ASSERT(ptrC != ptrB);
312     }
313 
314     // Conversion via assignment.
315     {
316         bool exists = false;
317         {
318             SharedPtr<Object> basePtr;
319             {
320                 SharedPtr<DerivedObject> derivedPtr(new DerivedObject(exists));
321                 DE_TEST_ASSERT(exists);
322                 basePtr = derivedPtr;
323                 DE_TEST_ASSERT(exists);
324             }
325             DE_TEST_ASSERT(exists);
326         }
327         DE_TEST_ASSERT(!exists);
328     }
329 
330     // Conversion via copy ctor.
331     {
332         bool exists = false;
333         {
334             SharedPtr<DerivedObject> derivedPtr(new DerivedObject(exists));
335             SharedPtr<Object> basePtr(derivedPtr);
336             DE_TEST_ASSERT(exists);
337             derivedPtr = SharedPtr<DerivedObject>();
338             DE_TEST_ASSERT(exists);
339         }
340         DE_TEST_ASSERT(!exists);
341     }
342 
343     // Explicit conversion operator.
344     {
345         bool exists = false;
346         {
347             SharedPtr<DerivedObject> derivedPtr(new DerivedObject(exists));
348             DE_TEST_ASSERT(exists);
349 
350             SharedPtr<Object> basePtr = (SharedPtr<Object>)(derivedPtr);
351             derivedPtr                = SharedPtr<DerivedObject>();
352             DE_TEST_ASSERT(exists);
353         }
354         DE_TEST_ASSERT(!exists);
355     }
356 
357     // Basic weak reference.
358     {
359         bool exists = false;
360         SharedPtr<Object> ptr(new Object(exists));
361         DE_TEST_ASSERT(exists);
362 
363         WeakPtr<Object> weakPtr(ptr);
364         try
365         {
366             SharedPtr<Object> newRef(weakPtr);
367             DE_TEST_ASSERT(exists);
368         }
369         catch (const DeadReferenceException &)
370         {
371             DE_TEST_ASSERT(false);
372         }
373 
374         ptr = SharedPtr<Object>();
375         DE_TEST_ASSERT(!exists);
376         try
377         {
378             SharedPtr<Object> newRef(weakPtr);
379             DE_TEST_ASSERT(false);
380         }
381         catch (const DeadReferenceException &)
382         {
383         }
384     }
385 
386     // Basic SharedPtr threaded test.
387     {
388         bool exists = false;
389         {
390             SharedPtr<Object> ptr(new Object(exists));
391 
392             SharedPtrTestThread threadA(ptr, exists);
393             SharedPtrTestThread threadB(ptr, exists);
394 
395             threadA.start();
396             threadB.start();
397 
398             threadA.join();
399             threadB.join();
400             DE_TEST_ASSERT(exists);
401         }
402         DE_TEST_ASSERT(!exists);
403     }
404 
405     // Basic WeakPtr threaded test.
406     {
407         bool exists = false;
408         {
409             SharedPtr<Object> ptr(new Object(exists));
410             WeakPtrTestThread threadA(ptr, exists);
411             WeakPtrTestThread threadB(ptr, exists);
412 
413             threadA.start();
414             threadB.start();
415 
416             threadA.join();
417             threadB.join();
418             DE_TEST_ASSERT(exists);
419         }
420         DE_TEST_ASSERT(!exists);
421     }
422 
423     // Basic custom deleter.
424     {
425         bool exists        = false;
426         bool deleterCalled = false;
427         {
428             SharedPtr<Object> ptr(new Object(exists), CustomDeleter(&deleterCalled));
429             DE_TEST_ASSERT(exists);
430             DE_TEST_ASSERT(!deleterCalled);
431             DE_TEST_ASSERT(ptr.get() != DE_NULL);
432         }
433         DE_TEST_ASSERT(!exists);
434         DE_TEST_ASSERT(deleterCalled);
435     }
436 }
437 
438 } // namespace de
439