GCC Code Coverage Report


Directory: codebase/
File: codebase/library/include/public/lib.SharedPointer.hpp
Date: 2023-03-16 04:37:09
Exec Total Coverage
Lines: 121 129 93.8%
Functions: 53 75 70.7%
Branches: 46 70 65.7%

Line Branch Exec Source
1 /**
2 * @file lib.SharedPointer.hpp
3 * @author Sergey Baigudin, sergey@baigudin.software
4 * @copyright 2020-2022, Sergey Baigudin, Baigudin Software
5 */
6 #ifndef LIB_SHAREDPOINTER_HPP_
7 #define LIB_SHAREDPOINTER_HPP_
8
9 #include "lib.Object.hpp"
10 #include "api.SmartPointer.hpp"
11 #include "lib.SmartPointerDeleter.hpp"
12 #include "lib.MutexGuard.hpp"
13 #include "lib.NonCopyable.hpp"
14
15 namespace eoos
16 {
17 namespace lib
18 {
19
20 #ifdef EOOS_ENABLE_DYNAMIC_HEAP_MEMORY
21
22 /**
23 * @class SharedPointer<T,D,A>
24 * @brief Shared pointer.
25 *
26 * @tparam T Data type of an owning object.
27 * @tparam D Deleter type for an owning object.
28 * @tparam A Heap memory allocator class.
29 */
30 template <typename T, class D = SmartPointerDeleter<T>, class A = Allocator>
31 class SharedPointer : public Object<A>, public api::SmartPointer<T>
32 {
33 typedef SharedPointer<T,D,A> Self;
34 typedef Object<A> Parent;
35
36 public:
37
38 /**
39 * @brief Constructor an empty shared object.
40 */
41 24 SharedPointer()
42 : Object<A>()
43 , api::SmartPointer<T>()
44 24 , cb_(NULLPTR) {
45
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
24 bool_t const isConstructed( construct() );
46 24 setConstructed(isConstructed);
47 24 }
48
49 /**
50 * @brief Constructor.
51 *
52 * @note If the shared object is not able to be constructed, an object passed by the pointer will be deleted.
53 *
54 * @param pointer A pointer to get ownership.
55 */
56 82 explicit SharedPointer(T* const pointer)
57 : Object<A>()
58 , api::SmartPointer<T>()
59 82 , cb_(NULLPTR) {
60
1/2
✓ Branch 1 taken 41 times.
✗ Branch 2 not taken.
82 bool_t const isConstructed( construct(pointer) );
61 82 setConstructed(isConstructed);
62 82 }
63
64 /**
65 * @brief Destructor.
66 */
67 132 virtual ~SharedPointer()
68 {
69
2/2
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 9 times.
124 if( isConstructed() )
70 {
71 106 release();
72 }
73 }
74
75 /**
76 * @copydoc eoos::Object::Object(Object const&)
77 */
78 16 SharedPointer(SharedPointer const& obj) ///< SCA MISRA-C++:2008 Justified Rule 12-8-1
79 : Object<A>(obj)
80 , api::SmartPointer<T>()
81 16 , cb_(obj.cb_){
82
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
16 acquire();
83 16 }
84
85 /**
86 * @copydoc eoos::Object::operator=(Object const&)
87 */
88 18 SharedPointer& operator=(SharedPointer const& obj)
89 {
90
5/6
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 8 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 1 times.
18 if( isConstructed() && (this != &obj) )
91 {
92 16 release();
93 16 cb_ = obj.cb_;
94 16 acquire();
95 16 Parent::operator=(obj);
96 }
97 18 return *this;
98 }
99
100 #if EOOS_CPP_STANDARD >= 2011
101
102 /**
103 * @copydoc eoos::Object::Object(Object&&)
104 */
105 1 SharedPointer(SharedPointer&& obj) noexcept
106 1 : Object<A>( move(obj) )
107 , api::SmartPointer<T>()
108 1 , cb_(obj.cb_) {
109 1 }
110
111 /**
112 * @copydoc eoos::Object::operator=(Object&&)
113 */
114 5 SharedPointer& operator=(SharedPointer&& obj) & noexcept
115 {
116
5/6
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 1 times.
5 if( isConstructed() && (this != &obj) )
117 {
118 4 release();
119 4 cb_ = obj.cb_;
120 4 Parent::operator=( move(obj) );
121 }
122 5 return *this;
123 }
124
125 #endif // EOOS_CPP_STANDARD >= 2011
126
127 /**
128 * @copydoc eoos::api::Object::isConstructed()
129 */
130 828 virtual bool_t isConstructed() const ///< SCA MISRA-C++:2008 Defected Rule 9-3-3
131 {
132 828 return Parent::isConstructed();
133 }
134
135 /**
136 * @brief Casts to boolean data type comparing if the stored pointer does not equal to null.
137 *
138 * @return Comparation the stored pointer does not equal to null.
139 */
140 3 operator bool_t() const
141 {
142 3 return get() != NULLPTR;
143 }
144
145 /**
146 * @brief Returns the result of dereferencing the stored pointer.
147 *
148 * @return The dereferenced stored pointer.
149 */
150 1 T& operator*() const
151 {
152 1 return *get();
153 }
154
155 /**
156 * @brief Returns the stored pointer.
157 *
158 * @return The stored pointer or NULLPTR if no pointer stored.
159 */
160 30 T* operator->() const
161 {
162 30 return get();
163 }
164
165 /**
166 * @brief Returns an element of the stored array.
167 *
168 * @param index An element index.
169 * @return An element.
170 */
171 9 T& operator[](uint32_t const index) const
172 {
173 9 T* const pointer( get() );
174 9 return pointer[index];
175 }
176
177 /**
178 * @copydoc eoos::api::SmartPointer::get()
179 */
180 218 virtual T* get() const
181 {
182 218 T* pointer( NULLPTR );
183
2/2
✓ Branch 1 taken 106 times.
✓ Branch 2 taken 3 times.
218 if( isConstructed() )
184 {
185 212 pointer = cb_->getPointer();
186 }
187 218 return pointer;
188 }
189
190 /**
191 * @copydoc eoos::api::SmartPointer::reset()
192 */
193 4 virtual void reset()
194 {
195 4 reset(NULLPTR);
196 }
197
198 /**
199 * @copydoc eoos::api::SmartPointer::reset(T*)
200 */
201 8 virtual void reset(T* ptr)
202 {
203
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
8 if (get() != ptr)
204 {
205
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
8 Self temp(ptr);
206
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
8 swap(temp);
207 }
208 }
209
210 /**
211 * @copydoc eoos::api::SmartPointer::getCount()
212 */
213 200 virtual int32_t getCount() const
214 {
215 200 int32_t counter( 0 );
216
2/2
✓ Branch 1 taken 88 times.
✓ Branch 2 taken 12 times.
200 if( isConstructed() )
217 {
218
2/2
✓ Branch 1 taken 66 times.
✓ Branch 2 taken 22 times.
176 if( cb_->getPointer() != NULLPTR )
219 {
220 132 counter = cb_->getCounter();
221 }
222 }
223 200 return counter;
224 }
225
226 /**
227 * @copydoc eoos::api::SmartPointer::isNull()
228 */
229 56 virtual bool_t isNull() const
230 {
231 56 return get() == NULLPTR;
232 }
233
234 /**
235 * @copydoc eoos::api::SmartPointer::isUnique()
236 */
237 56 virtual bool_t isUnique() const
238 {
239 56 return getCount() == 1;
240 }
241
242 /**
243 * @brief Swaps this managed object with an object managed by given smart object.
244 *
245 * @param obj A smart object to swap managed objects.
246 */
247 12 void swap(SharedPointer& obj)
248 {
249
3/6
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
12 if( isConstructed() && obj.isConstructed() )
250 {
251 12 ControlBlock<T,D,A>* const cb( cb_ );
252 12 cb_ = obj.cb_;
253 12 obj.cb_ = cb;
254 }
255 }
256
257 protected:
258
259 using Parent::setConstructed;
260
261 private:
262
263 /**
264 * @brief Constructs this object.
265 *
266 * @param pointer A pointer to get ownership.
267 * @return True if this object has been constructed successfully.
268 */
269 106 bool_t construct(T* const pointer = NULLPTR)
270 {
271 106 bool_t res( false );
272 do
273 {
274
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 53 times.
106 if( !isConstructed() )
275 { ///< UT Justified Branch: HW dependency
276 D::free(pointer);
277 break;
278 }
279
3/4
✓ Branch 1 taken 51 times.
✓ Branch 2 taken 2 times.
✓ Branch 4 taken 51 times.
✗ Branch 5 not taken.
106 cb_ = new ControlBlock<T,D,A>(pointer);
280
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 51 times.
106 if(cb_ == NULLPTR)
281 {
282 4 D::free(pointer);
283 4 break;
284 }
285
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 51 times.
102 if( !cb_->isConstructed() )
286 { ///< UT Justified Branch: HW dependency
287 D::free(pointer);
288 delete cb_;
289 cb_ = NULLPTR;
290 break;
291 }
292 102 res = true;
293 } while(false);
294 106 return res;
295 }
296
297 /**
298 * @brief Releases the managed object by control block.
299 */
300 130 void release()
301 {
302
1/2
✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
130 if( cb_ != NULLPTR )
303 {
304 130 int32_t const counter( cb_->decrease() );
305
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 15 times.
130 if(counter == 0)
306 {
307 100 D::free(cb_->getPointer());
308
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
100 delete cb_;
309 100 cb_ = NULLPTR;
310 }
311 }
312 }
313
314 /**
315 * @brief Acquires a managed object by control block.
316 */
317 32 void acquire()
318 {
319
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 1 times.
32 if( cb_ != NULLPTR )
320 {
321 30 cb_->increase();
322 }
323 32 }
324
325 /**
326 * @class ControlBlock<TT,DD,AA>
327 * @brief Primary template implementation of shared pointer control block class.
328 *
329 * @tparam TT Data type of owning the object.
330 * @tparam DD Deleter type for owning the object.
331 * @tparam AA Heap memory allocator class.
332 *
333 * @note This class is implemented as an auxiliry class for SharedPointer
334 * and is tested for construction before usage. Therefore, some checks
335 * are skipped in public interface to speedup performence.
336 */
337 template <typename TT, class DD, class AA>
338 class ControlBlock : public NonCopyable<AA>
339 {
340 typedef NonCopyable<AA> Parent;
341
342 public:
343
344 /**
345 * @brief Constructor.
346 *
347 * @param pointer A pointer to get ownership.
348 */
349 102 explicit ControlBlock(T* const pointer)
350 : NonCopyable<AA>()
351 102 , pointer_(pointer)
352 102 , counter_(1)
353
1/2
✓ Branch 2 taken 51 times.
✗ Branch 3 not taken.
102 , mutex_() {
354
1/2
✓ Branch 1 taken 51 times.
✗ Branch 2 not taken.
102 bool_t const isConstructed( construct() );
355 102 setConstructed(isConstructed);
356 }
357
358 /**
359 * @copydoc eoos::api::Object::isConstructed()
360 */
361 204 virtual bool_t isConstructed() const
362 {
363 204 return Parent::isConstructed();
364 }
365
366 /**
367 * @brief Destructor.
368 */
369 200 virtual ~ControlBlock() {}
370
371 /**
372 * @brief Increases the counter on one.
373 */
374 30 void increase()
375 {
376
1/2
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
30 MutexGuard<AA> const guard(mutex_);
377 static_cast<void>(guard);
378 30 ++counter_;
379 }
380
381 /**
382 * @brief Decreases the counter on one.
383 *
384 * @return A value of the counter after decreasing.
385 */
386 130 int32_t decrease()
387 {
388
1/2
✓ Branch 1 taken 65 times.
✗ Branch 2 not taken.
130 MutexGuard<AA> const guard(mutex_);
389 static_cast<void>(guard);
390 130 return --counter_;
391 }
392
393 /**
394 * @brief Returns the counter.
395 *
396 * @return A value of the counter.
397 */
398 132 int32_t getCounter() const
399 {
400 132 return counter_;
401 }
402
403 /**
404 * @brief Returns the managed raw pointer.
405 *
406 * @return The managed raw pointer.
407 */
408 488 TT* getPointer() const
409 {
410 488 return pointer_;
411 }
412
413 private:
414
415 /**
416 * @brief Constructs this object.
417 */
418 102 bool_t construct()
419 {
420 102 bool_t res( false );
421 do
422 {
423
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 51 times.
102 if( !isConstructed() )
424 { ///< UT Justified Branch: HW dependency
425 break;
426 }
427
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 51 times.
102 if( !mutex_.isConstructed() )
428 { ///< UT Justified Branch: HW dependency
429 break;
430 }
431 102 res = true;
432 } while(false);
433 102 return res;
434 }
435
436 /**
437 * @brief An owned pointer.
438 */
439 TT* pointer_;
440
441 /**
442 * @brief Counter of copies of the shared objects.
443 */
444 int32_t counter_;
445
446 /**
447 * @brief Mutex to protect the counter.
448 */
449 Mutex<AA> mutex_;
450 };
451
452 /**
453 * @brief Control block of the managed object.
454 */
455 ControlBlock<T,D,A>* cb_;
456
457 };
458
459 /**
460 * @brief Comparison operator to equal.
461 *
462 * @param obj1 Reference to object.
463 * @param obj2 Reference to object.
464 * @return True if objects are equal.
465 */
466 template <typename T, class D = SmartPointerDeleter<T>, class A = Allocator>
467 2 inline bool_t operator==(SharedPointer<T,D,A> const& obj1, SharedPointer<T,D,A> const& obj2)
468 {
469 2 return obj1.get() == obj2.get();
470 }
471
472 /**
473 * @brief Comparison operator to unequal.
474 *
475 * @param obj1 Reference to object.
476 * @param obj2 Reference to object.
477 * @return True if objects are not equal.
478 */
479 template <typename T, class D = SmartPointerDeleter<T>, class A = Allocator>
480 2 inline bool_t operator!=(SharedPointer<T,D,A> const& obj1, SharedPointer<T,D,A> const& obj2)
481 {
482 2 return obj1.get() != obj2.get();
483 }
484
485 #endif // EOOS_ENABLE_DYNAMIC_HEAP_MEMORY
486
487 } // namespace lib
488 } // namespace eoos
489 #endif // LIB_SHAREDPOINTER_HPP_
490