GCC Code Coverage Report


Directory: ./
File: lib/geogram/basic/life_cycle.h
Date: 2026-09-07 02:36:43
Exec Total Coverage
Lines: 9 66 13.6%
Functions: 3 18 16.7%
Branches: 0 46 0.0%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2000-2022 Inria
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * * Neither the name of the ALICE Project-Team nor the names of its
14 * contributors may be used to endorse or promote products derived from this
15 * software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Contact: Bruno Levy
30 *
31 * https://www.inria.fr/fr/bruno-levy
32 *
33 * Inria,
34 * Domaine de Voluceau,
35 * 78150 Le Chesnay - Rocquencourt
36 * FRANCE
37 *
38 */
39
40 #ifndef GEOGRAM_BASIC_LIFE_CYCLE
41 #define GEOGRAM_BASIC_LIFE_CYCLE
42
43 #include <geogram/basic/common.h>
44 #include <geogram/basic/memory.h>
45 #include <geogram/basic/counted.h>
46
47 /**
48 * \file geogram/basic/life_cycle.h
49 * \brief Implementation of generic object lifecycle service
50 */
51
52 #ifdef GEO_COMPILER_CLANG
53 #pragma GCC diagnostic push
54 #pragma GCC diagnostic ignored "-Wcast-align"
55 #endif
56
57 namespace GEO {
58
59 /**
60 * \brief Manages the life cycle of an object.
61 * \details Provides ways to call the constructor, destructor, copy
62 * constructor and assignation operator on objects known only from
63 * their addresses as raw untyped pointers. This is used by the
64 * Attribute mechanism of Geogram and by the Any class in Graphite/GOM.
65 */
66 class GEOGRAM_API LifeCycle : public Counted {
67 public:
68
69 /**
70 * \brief LifeCycle constructor.
71 * \param[in] object_size the size of an object in bytes.
72 */
73 1 LifeCycle(size_t object_size, bool is_pod=false) :
74 1 object_size_(object_size), is_pod_(is_pod) {
75 1 }
76
77 /**
78 * \brief LifeCycle destructor.
79 */
80 ~LifeCycle() override;
81
82 /**
83 * \brief Gets the size of an object.
84 * \return the size of an object in bytes.
85 */
86 size_t object_size() const {
87 return object_size_;
88 }
89
90 /**
91 * \brief Tests whether object is pod (plain ordinary
92 * datatype).
93 * \details Plain ordinary datatypes can be copied with
94 * memcpy().
95 * \retval true if object is pod.
96 * \retval false otherwise.
97 */
98 bool is_pod() const {
99 return is_pod_;
100 }
101
102 /**
103 * \brief Calls the constructor of an object.
104 * \param[in] address the address of the object
105 * to be constructed.
106 * \details No memory allocation is done.
107 */
108 virtual void construct(Memory::pointer address) = 0;
109
110 /**
111 * \brief Copy-Constructs an object at a given address.
112 * \param[in] lhs the address where the object should
113 * be constructed.
114 * \param[in] rhs the address of the right-hand-side object
115 * to be copied.
116 * \details No memory allocation is done.
117 */
118 virtual void copy_construct(
119 Memory::pointer lhs, Memory::const_pointer rhs
120 ) = 0;
121
122 /**
123 * \brief Calls the destructor of an object.
124 * \param[in] address the address of the object to be destructed.
125 * \details No memory deallocation is done.
126 */
127 virtual void destroy(Memory::pointer address) = 0;
128
129 /**
130 * \brief Calls the assignment operator.
131 * \param[in] lhs the address of the left hand side.
132 * \param[in] rhs the address of the right hand side.
133 */
134 virtual void assign(Memory::pointer lhs, Memory::const_pointer rhs) = 0;
135
136 /**
137 * \brief Resets an object to its default value.
138 * \details Creates a new object with the default constructor and assigns
139 * it to the object at \p address.
140 * \param[in] address the address of an already initialized object.
141 */
142 virtual void reset(Memory::pointer address) = 0;
143
144
145 /**
146 * \brief Swaps the objects at two addresses
147 * \param[in] a , b pointers to the two objects to be swapped
148 */
149 virtual void swap(Memory::pointer a, Memory::pointer b) = 0;
150
151 /**
152 * \brief Calls the constructor of objects in an array.
153 * \param[in] address the address of the object array
154 * to be constructed.
155 * \param[in] nb number of objects.
156 * \details No memory allocation is done.
157 */
158 virtual void construct_array(Memory::pointer address, index_t nb) = 0;
159
160 /**
161 * \brief Copy-Constructs an array of object at a given address.
162 * \param[in] lhs the address of the objects to be constructed.
163 * \param[in] rhs the address of the right-hand-side objects
164 * to be copied.
165 * \param[in] nb number of objects
166 * \details No memory allocation is done.
167 */
168 virtual void copy_construct_array(
169 Memory::pointer lhs, Memory::const_pointer rhs, index_t nb
170 ) = 0;
171
172 /**
173 * \brief Destroys an array of object at a given address.
174 * \param[in] address the address of the objects to be destroyed.
175 * \param[in] nb number of objects
176 * \details No memory deallocation is done.
177 */
178 virtual void destroy_array(Memory::pointer address, index_t nb) = 0;
179
180 /**
181 * \brief Copies an array of object at a given address.
182 * \param[in] lhs the address of the left-hand-side objects
183 * \param[in] rhs the address of the right-hand-side objects
184 * to be copied.
185 * \param[in] nb number of objects
186 * \details No memory allocation is done.
187 */
188 virtual void assign_array(
189 Memory::pointer lhs, Memory::const_pointer rhs, index_t nb
190 ) = 0;
191
192
193 /**
194 * \brief Resets all objects in an array to their default value.
195 * \details creates an object with the default value and assigns
196 * it to the element for each element in the array.
197 * \param[in] address the address of the object array
198 * to be reset.
199 * \param[in] nb number of objects.
200 */
201 virtual void reset_array(Memory::pointer address, index_t nb) = 0;
202
203 /**
204 * \brief Dynamically allocates a new object.
205 * \return the address of the new object.
206 */
207 virtual Memory::pointer new_object() = 0;
208
209 /**
210 * \brief Dynamically allocates a new object with copy constructor.
211 * \param[in] rhs the address of the right-hand-side objects
212 * to be copied.
213 * \return the address of the new object.
214 */
215 virtual Memory::pointer new_object(Memory::const_pointer rhs) = 0;
216
217 /**
218 * \brief Deletes an object.
219 * \param[in] address the address of the object.
220 */
221 virtual void delete_object(Memory::pointer address) = 0;
222
223 /**
224 * \brief Dynamically allocates an array of objects.
225 * \param[in] nb number of objects.
226 */
227 virtual Memory::pointer new_array(index_t nb) = 0;
228
229 /**
230 * \brief Deletes an array of objects.
231 * \param[in] address the address of the object array to
232 * be deleted.
233 */
234 virtual void delete_array(Memory::pointer address) = 0;
235
236
237 private:
238 size_t object_size_;
239 bool is_pod_;
240 };
241
242 /**
243 * \brief A reference_counted pointer to a LifeCycle.
244 */
245 typedef SmartPointer<LifeCycle> LifeCycle_var;
246
247 /*************************************************************************/
248
249 /**
250 * \brief Concrete implementation of LifeCycle.
251 */
252 template <class T> class GenericLifeCycle : public LifeCycle {
253 public:
254
255 /**
256 * \brief GenericLifeCycle constructor.
257 */
258 1 GenericLifeCycle() :
259 LifeCycle(
260 sizeof(T),
261 (std::is_standard_layout<T>::value && std::is_trivial<T>::value)
262 1 ) {
263 1 }
264
265 /**
266 * \copydoc LifeCycle::construct()
267 */
268 void construct(Memory::pointer address) override {
269 new(address)T;
270 }
271
272 /**
273 * \copydoc LifeCycle::copy_construct()
274 */
275 void copy_construct(
276 Memory::pointer lhs, Memory::const_pointer rhs
277 ) override {
278 new(lhs)T(*(const T*)rhs);
279 }
280
281 /**
282 * \copydoc LifeCycle::destroy()
283 */
284 void destroy(Memory::pointer address) override {
285 geo_argused(address); // Silences a MSVC warning.
286 ((T*)address)->~T();
287 }
288
289 /**
290 * \copydoc LifeCycle::assign()
291 */
292 void assign(Memory::pointer lhs, Memory::const_pointer rhs) override {
293 *(T*)lhs=*(const T*)rhs;
294 }
295
296 /**
297 * \copydoc LifeCycle::reset()
298 */
299 81900 void reset(Memory::pointer address) override {
300 81900 *(T*)address = T();
301 81900 }
302 /**
303 * \copydoc LifeCycle::swap()
304 */
305 void swap(Memory::pointer a, Memory::pointer b) override {
306 std::swap(*(T*)a, *(T*)b);
307 }
308
309 /**
310 * \copydoc LifeCycle::construct_array()
311 */
312 void construct_array(Memory::pointer address, index_t nb) override {
313 T* array = (T*)address;
314 for(index_t i=0; i<nb; ++i) {
315 new(&array[i])T;
316 }
317 }
318
319 /**
320 * \copydoc LifeCycle::copy_construct_array()
321 */
322 void copy_construct_array(
323 Memory::pointer lhs, Memory::const_pointer rhs, index_t nb
324 ) override {
325 T* lhs_array = (T*)lhs;
326 const T* rhs_array = (const T*)rhs;
327 for(index_t i=0; i<nb; ++i) {
328 new(&lhs_array[i])T(rhs_array[i]);
329 }
330 }
331
332 /**
333 * \copydoc LifeCycle::destroy_array()
334 */
335 void destroy_array(Memory::pointer address, index_t nb) override {
336 T* array = (T*)address;
337 geo_argused(array); // Silences a MSVC warning.
338 for(index_t i=0; i<nb; ++i) {
339 array[i].~T();
340 }
341 }
342
343 /**
344 * \copydoc LifeCycle::assign_array()
345 */
346 void assign_array(
347 Memory::pointer lhs, Memory::const_pointer rhs, index_t nb
348 ) override {
349 T* lhs_array = (T*)lhs;
350 const T* rhs_array = (const T*)rhs;
351 for(index_t i=0; i<nb; ++i) {
352 lhs_array[i] = rhs_array[i];
353 }
354 }
355
356 /**
357 * \copydoc LifeCycle::reset_array()
358 */
359 void reset_array(Memory::pointer address, index_t nb) override {
360 T* array = (T*)address;
361 geo_argused(array); // Silences a MSVC warning.
362 for(index_t i=0; i<nb; ++i) {
363 array[i] = T();
364 }
365 }
366
367 /**
368 * \copydoc LifeCycle::new_object()
369 */
370 Memory::pointer new_object() override {
371 return Memory::pointer(new T);
372 }
373
374 /**
375 * \copydoc LifeCycle::new_object()
376 */
377 Memory::pointer new_object(Memory::const_pointer rhs) override {
378 return Memory::pointer(new T(*(const T*)rhs));
379 }
380
381 /**
382 * \copydoc LifeCycle::delete_object()
383 */
384 void delete_object(Memory::pointer address) override {
385 delete((T*)address);
386 }
387
388 /**
389 * \copydoc LifeCycle::new_array()
390 */
391 Memory::pointer new_array(index_t nb) override {
392 return Memory::pointer(new T[nb]);
393 }
394
395 /**
396 * \copydoc LifeCycle::delete_array()
397 */
398 void delete_array(Memory::pointer address) override {
399 delete[]((T*)address);
400 }
401
402 };
403
404 }
405
406 #ifdef GEO_COMPILER_CLANG
407 #pragma GCC diagnostic pop
408 #endif
409
410 #endif
411