CAEN Utility  2.0.2
Utilities for CAEN projects
CAENAllocator.c
Go to the documentation of this file.
1 /******************************************************************************
2 *
3 * CAEN SpA - Software Division
4 * Via Vetraia, 11 - 55049 - Viareggio ITALY
5 * +39 0594 388 398 - www.caen.it
6 *
7 *******************************************************************************
8 *
9 * Copyright (C) 2019-2022 CAEN SpA
10 *
11 * This file is part of the CAEN Utility.
12 *
13 * The CAEN Utility is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Lesser General Public
15 * License as published by the Free Software Foundation; either
16 * version 3 of the License, or (at your option) any later version.
17 *
18 * The CAEN Utility is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * Lesser General Public License for more details.
22 *
23 * You should have received a copy of the GNU Lesser General Public
24 * License along with the CAEN Utility; if not, see
25 * https://www.gnu.org/licenses/.
26 *
27 * SPDX-License-Identifier: LGPL-3.0-or-later
28 *
29 ******************************************************************************
30 *
31 * \file CAENAllocator.c
32 * \brief Utilities to handle memory allocation in C minimizing memory leaks
33 * \author Francesco Pepe
34 *
35 ******************************************************************************/
36 
37 #include <CAENAllocator.h>
38 
39 #include <CAENMultiplatform.h>
40 #include <CAENLinkedList.h>
41 
43  c_allocator_t res;
44  res.error_count = 0;
46  return res;
47 }
48 
49 typedef struct {
50  void* resource;
53 
55  if (allocator == NULL)
56  return NULL;
57 
58  // Check if resource is NULL (allocation/creation may have failed in caller)
59  if (resource == NULL) {
60  allocator->error_count++;
61  return NULL;
62  }
63 
64  _c_resource_t* res = c_calloc(1, sizeof(_c_resource_t));
65  if (res == NULL) {
66  if (resource != NULL)
67  df(resource);
68  allocator->error_count++;
69  return NULL;
70  }
71 
72  res->resource = resource;
73  res->destroy = df;
74 
76  c_free(res);
77  if (resource != NULL)
78  df(resource);
79  allocator->error_count++;
80  return NULL;
81  }
82 
83  return resource;
84 }
85 
87  return c_allocator_resource_create(allocator, c_free, c_malloc(size));
88 }
89 
90 c_use_decl_annotations void* c_allocator_calloc(c_allocator_t* allocator, size_t nmemb, size_t size) {
91  return c_allocator_resource_create(allocator, c_free, c_calloc(nmemb, size));
92 }
93 
95  return allocator->error_count;
96 }
97 
98 static int _resource_comparator(const void* r, const void* d) {
99  // as per 'c_linkedlist_delete_data_compare', i-th list element is passed as
100  // first argument, while given 'data' pointer is passed as second.
101  return ((const _c_resource_t*)r)->resource == d;
102 }
103 
104 static void _allocator_release_or_destroy(c_allocator_t* allocator, void* ptr, bool destroy) {
106  if (destroy)
107  resource->destroy(resource->resource);
108  if (resource != NULL)
109  c_free(resource);
110 }
111 
112 void c_allocator_release(c_allocator_t* allocator, void* ptr) {
113  _allocator_release_or_destroy(allocator, ptr, false);
114 }
115 
117  allocator->error_count = 0;
118  while (allocator->allocated_resources.head != NULL) {
120  c_free(resource);
121  }
122 }
123 
124 void c_allocator_free(c_allocator_t* allocator, void* ptr) {
125  _allocator_release_or_destroy(allocator, ptr, true);
126 }
127 
129  if (allocator == NULL)
130  return;
131  for (c_listnode_t* node = allocator->allocated_resources.head; node != NULL; node = node->next) {
132  _c_resource_t* resource = node->data;
133  resource->destroy(resource->resource);
134  // resource pointer free done in 'c_allocator_clear'
135  }
136  c_allocator_clear(allocator);
137 }
c_Utility_ErrorCode_t c_linkedlist_insert_first(c_linkedlist_t *list, void *newElement)
void c_free(void *ptr)
void * c_calloc(size_t nmemb, size_t size)
c_linkedlist_t c_linkedlist_create()
struct c_listnode_t * next
void * c_linkedlist_delete_data_compare(c_linkedlist_t *list, void *data, c_listdata_comparator_t cmp)
void c_allocator_free(c_allocator_t *allocator, void *ptr)
void * c_allocator_malloc(c_allocator_t *allocator, size_t size)
Definition: CAENAllocator.c:86
c_resource_destroy_function destroy
Definition: CAENAllocator.c:51
c_listnode_t * head
static int _resource_comparator(const void *r, const void *d)
Definition: CAENAllocator.c:98
c_allocator_t c_allocator_create()
Definition: CAENAllocator.c:42
static void _allocator_release_or_destroy(c_allocator_t *allocator, void *ptr, bool destroy)
void * c_malloc(size_t size)
Generic wrappers to platform-dependent functions.
void(* c_resource_destroy_function)(void *)
void c_allocator_clear(c_allocator_t *allocator)
void * c_linkedlist_delete_first(c_linkedlist_t *list)
#define c_use_decl_annotations
Definition: CAENUtility.h:278
void c_allocator_release(c_allocator_t *allocator, void *ptr)
int32_t c_allocator_error_count(const c_allocator_t *allocator)
Definition: CAENAllocator.c:94
void c_allocator_freeall(c_allocator_t *allocator)
void * c_allocator_resource_create(c_allocator_t *allocator, c_resource_destroy_function df, void *resource)
Definition: CAENAllocator.c:54
c_linkedlist_t allocated_resources
void * c_allocator_calloc(c_allocator_t *allocator, size_t nmemb, size_t size)
Definition: CAENAllocator.c:90