Adaptive Framework  0.9.0
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
afw_pool_singlethreaded.c
Go to the documentation of this file.
1 // See the 'COPYING' file in the project root for licensing information.
2 /*
3  * Adaptive Framework Singlethreaded pool implementation.
4  *
5  * Copyright (c) 2010-2023 Clemson University
6  *
7  */
8 
14 #include "afw_internal.h"
15 
16 
17 
18 #ifdef AFW_POOL_DEBUG
19 #undef afw_pool_create
20 #undef afw_pool_internal_create_thread
21 #endif
22 
23 #define AFW_IMPLEMENTATION_ID "afw_pool_singlethreaded"
24 #include "afw_pool_impl_declares.h"
25 
27 #define IMPL_DEBUG_LEVEL_detail flag_index_debug_pool_detail
28 #define IMPL_DEBUG_LEVEL_minimal flag_index_debug_pool
29 
30 #define IMPL_PRINT_DEBUG_INFO_Z(level,info_z) \
31 do { \
32  const afw_utf8_t *trace; \
33  if (afw_flag_is_active(xctx->env->IMPL_DEBUG_LEVEL_##level, xctx)) \
34  { \
35  trace = afw_os_backtrace(0, -1, xctx); \
36  afw_debug_write_fz(NULL, source_z, xctx, \
37  "pool %" AFW_INTEGER_FMT " " \
38  info_z \
39  ": before %" AFW_SIZE_T_FMT \
40  " refs %" AFW_INTEGER_FMT \
41  " parent %" AFW_INTEGER_FMT \
42  " single" \
43  "%s" \
44  "%" AFW_UTF8_FMT, \
45  self->pool_number, \
46  (self->bytes_allocated), \
47  (self->reference_count), \
48  (afw_integer_t)((self->parent) ? self->parent->pool_number : 0), \
49  (char *)((trace) ? "\n" : ""), \
50  (int)((trace) ? (int)trace->len : 0), \
51  (const char *)((trace) ? (const char *)trace->s : "") \
52  ); \
53  } \
54 } while (0) \
55 
56 
57 #define IMPL_PRINT_DEBUG_INFO_FZ(level,format_z,...) \
58 do { \
59  const afw_utf8_t *trace; \
60  if (afw_flag_is_active(xctx->env->IMPL_DEBUG_LEVEL_##level, xctx)) \
61  { \
62  trace = afw_os_backtrace(0, -1, xctx); \
63  afw_debug_write_fz(NULL, source_z, xctx, \
64  "pool %" AFW_INTEGER_FMT " " \
65  format_z \
66  ": before %" AFW_SIZE_T_FMT \
67  " refs %" AFW_INTEGER_FMT \
68  " parent %" AFW_INTEGER_FMT \
69  " single" \
70  "%s" \
71  "%" AFW_UTF8_FMT, \
72  self->pool_number, \
73  __VA_ARGS__, \
74  (self->bytes_allocated), \
75  (self->reference_count), \
76  (afw_integer_t)((self->parent) ? self->parent->pool_number : 0), \
77  (char *)((trace) ? "\n" : ""), \
78  (int)((trace) ? (int)trace->len : 0), \
79  (const char *)((trace) ? (const char *)trace->s : "") \
80  ); \
81  } \
82 } while (0) \
83 
84 
85 static void
86 impl_add_child(afw_pool_internal_singlethreaded_self_t *parent,
88 {
89  afw_pool_add_reference(&parent->pub, xctx);
90 
91  child->next_sibling = parent->first_child;
92  parent->first_child = child;
93 }
94 
95 
96 static void
97 impl_remove_child(afw_pool_internal_singlethreaded_self_t *parent,
99 {
102 
103  for (prev = NULL, sibling = parent->first_child;
104  sibling;
105  prev = sibling, sibling = sibling->next_sibling)
106  {
107  if (sibling == child) {
108  if (!prev) {
109  parent->first_child = sibling->next_sibling;
110  }
111  else {
112  prev->next_sibling = sibling->next_sibling;
113  }
114  break;
115  }
116  }
117 
118  if (!sibling) {
119  AFW_THROW_ERROR_Z(general, "Not a child of parent", xctx);
120  }
121 
122  afw_pool_release(&parent->pub, xctx);
123 }
124 
125 
126 /* Create skeleton pool struct. */
128 impl_pool_create(afw_pool_internal_singlethreaded_self_t *parent, afw_xctx_t *xctx)
129 {
130  apr_pool_t *apr_p;
132 
133  apr_pool_create(&apr_p, (parent) ? parent->apr_p : NULL);
134  if (!apr_p) {
135  AFW_THROW_ERROR_Z(memory, "Unable to allocate pool", xctx);
136  }
137  self = apr_pcalloc(apr_p, sizeof(afw_pool_internal_singlethreaded_self_t));
138  if (!self) {
139  AFW_THROW_ERROR_Z(memory, "Unable to allocate pool", xctx);
140  }
141  self->pub.inf = &impl_afw_pool_inf;
142  self->apr_p = apr_p;
143  self->reference_count = 1;
144  self->parent = parent;
146  &((afw_environment_t *)xctx->env)->pool_number);
147 
148  /* If parent, add this new child. */
149  if (parent) {
150  impl_add_child(parent, self, xctx);
151  }
152 
153  /* Return new pool. */
154  return self;
155 }
156 
157 
158 AFW_DEFINE(const afw_pool_t *)
160  const afw_pool_t *parent, afw_xctx_t *xctx)
161 {
163 
164  /* Create skeleton pool stuct. */
165  self = impl_pool_create((afw_pool_internal_singlethreaded_self_t *)parent, xctx);
166 
167  /* Parent is required. */
168  if (!parent) {
169  AFW_THROW_ERROR_Z(general, "Parent required", xctx);
170  }
171 
172  /* If thread specific parent pool, this one is as well for same thread. */
173  if (((afw_pool_internal_singlethreaded_self_t *)parent)->thread) {
174  self->thread = xctx->thread;
175  }
176 
177  /* Return new pool. */
178  return (const afw_pool_t *)self;
179 }
180 
181 
182 AFW_DEFINE(const afw_pool_t *)
184  const afw_pool_t *parent,
185  afw_xctx_t *xctx, const afw_utf8_z_t *source_z)
186 {
189 
190  IMPL_PRINT_DEBUG_INFO_FZ(minimal,
191  "afw_pool_create %" AFW_INTEGER_FMT,
192  ((const afw_pool_internal_singlethreaded_self_t *)parent)->pool_number);
193 
194  return (const afw_pool_t *)self;
195 }
196 
197 
198 
199 /* Create a new thread specific pool for xctx. */
201 afw_pool_internal_create_thread(
202  afw_size_t size,
203  afw_xctx_t *xctx)
204 {
206  afw_thread_t *thread;
207 
208  if (size == -1 || size < sizeof(afw_thread_t)) {
209  size = sizeof(afw_thread_t);
210  }
211  self = impl_pool_create(NULL, xctx);
212  thread = apr_pcalloc(self->apr_p, size);
213  self->thread = thread;
214  thread->p = (const afw_pool_t *)self;
215 
216  return thread;
217 }
218 
219 
220 
221 /* Debug version of create a new thread specific pool for xctx. */
223 afw_pool_internal_create_thread_debug(
224  afw_size_t size,
225  afw_xctx_t *xctx, const afw_utf8_z_t *source_z)
226 {
227  afw_thread_t *thread =
228  afw_pool_internal_create_thread(size, xctx);
231 
232  IMPL_PRINT_DEBUG_INFO_FZ(minimal,
233  "afw_pool_internal_create_thread %" AFW_SIZE_T_FMT,
234  size);
235 
236  return thread;
237 }
238 
239 
240 
241 /*
242  * Implementation of method release for interface afw_pool.
243  */
244 void
246  const afw_pool_t * instance,
247  afw_xctx_t *xctx)
248 {
251 
252  /* If instance is NULL, just return. */
254  if (!instance) return;
255 
256  /* Decrement reference count and release pools resources if zero. */
257  if (--(self->reference_count) == 0) {
258  afw_pool_destroy(instance, xctx);
259  }
260 }
261 
262 /*
263  * Implementation of method add_reference for interface afw_pool.
264  */
265 void
266 impl_afw_pool_add_reference(
267  const afw_pool_t * instance,
268  afw_xctx_t *xctx)
269 {
271 
272  /* If instance is NULL, just return. */
273  if (!instance) return;
274 
275  /* Decrement reference count. */
276  self = (afw_pool_internal_singlethreaded_self_t *)instance;
277  self->reference_count++;
278 }
279 
280 /*
281  * Implementation of method destroy for interface afw_pool.
282  */
283 void
284 impl_afw_pool_destroy(
285  const afw_pool_t * instance,
286  afw_xctx_t *xctx)
287 {
292 
293  /* If instance is NULL, just return. */
294  if (!instance) return;
295 
296  /*
297  * Call all of the cleanup routines for this pool before destroying
298  * children.
299  */
300  for (e = self->first_cleanup; e; e = e->next_cleanup) {
301  e->cleanup(e->data, e->data2, instance, xctx);
302  }
303 
304  /*
305  * Destroy children.
306  *
307  * Release of child sets self->first_child to its next sibling.
308  */
309  for (child = self->first_child;
310  child;
311  child = self->first_child)
312  {
313  afw_pool_destroy((const afw_pool_t *)child, xctx);
314  }
315 
316  /* If parent, removed self as child. */
317  if (self->parent) {
318  impl_remove_child(self->parent, self, xctx);
319  }
320 
321  /* Destroy apr pool. */
322  apr_pool_destroy(self->apr_p);
323 }
324 
325 /*
326  * Implementation of method get_apr_pool for interface afw_pool.
327  */
328 apr_pool_t *
330  const afw_pool_t * instance)
331 {
334  int rv;
335 
336  if (!self->apr_p) {
337  rv = apr_pool_create(&self->apr_p,
338  (self->parent) ? self->parent->apr_p : NULL);
339  if (rv != APR_SUCCESS) {
341  //rv = 0/0;
342  }
343  }
344 
345  return self->apr_p;
346 }
347 
348 /*
349  * Implementation of method calloc for interface afw_pool.
350  */
351 void *
352 impl_afw_pool_calloc(
353  const afw_pool_t * instance,
354  afw_size_t size,
355  afw_xctx_t *xctx)
356 {
359  void *result;
360 
361  /* Don't allow allocate for a size of 0. */
362  if (size == 0) {
363  AFW_THROW_ERROR_Z(general,
364  "Attempt to allocate memory for a size of 0",
365  xctx);
366  }
367 
368  result = apr_pcalloc(self->apr_p, size);
369  self->bytes_allocated += size;
370 
371  if (!result) {
372  AFW_THROW_ERROR_Z(memory, "Allocate memory error.", xctx);
373  }
374 
375  return result;
376 }
377 
378 /*
379  * Implementation of method malloc for interface afw_pool.
380  */
381 void *
382 impl_afw_pool_malloc(
383  const afw_pool_t * instance,
384  afw_size_t size,
385  afw_xctx_t *xctx)
386 {
389  void *result;
390 
391  /* Don't allow allocate for a size of 0. */
392  if (size == 0) {
393  AFW_THROW_ERROR_Z(general,
394  "Attempt to allocate memory for a size of 0",
395  xctx);
396  }
397 
398  result = apr_palloc(self->apr_p, size);
399  self->bytes_allocated += size;
400 
401  if (!result) {
402  AFW_THROW_ERROR_Z(memory, "Allocate memory error.", xctx);
403  }
404 
405  return result;
406 }
407 
408 /*
409  * Implementation of method free for interface afw_pool.
410  */
411 void
413  const afw_pool_t * instance,
414  void * address,
415  afw_size_t size,
416  afw_xctx_t *xctx)
417 {
419  AFW_THROW_ERROR_Z(general, "Method not implemented.", xctx);
420 
421 }
422 
423 /*
424  * Implementation of method register_cleanup_before for interface afw_pool.
425  */
426 void
427 impl_afw_pool_register_cleanup_before(
428  const afw_pool_t * instance,
429  void * data,
430  void * data2,
432  afw_xctx_t *xctx)
433 {
437 
438  /* Allocate entry which will also make sure its ok to use pool. */
439  e = afw_pool_calloc_type(instance, afw_pool_cleanup_t, xctx);
440 
441  /* Add entry to front of list of cleanup functions. */
442  e->data = data;
443  e->data2 = data2;
444  e->cleanup = cleanup;
445  e->next_cleanup = self->first_cleanup;
446  self->first_cleanup = e;
447 }
448 
449 /*
450  * Implementation of method deregister_cleanup for interface afw_pool.
451  */
452 void
453 impl_afw_pool_deregister_cleanup(
454  const afw_pool_t * instance,
455  void * data,
456  void * data2,
458  afw_xctx_t *xctx)
459 {
462  afw_pool_cleanup_t *e, *prev;
463 
464  /* Search for entry and remove. */
465  for (prev = (afw_pool_cleanup_t *)& self->first_cleanup,
466  e = self->first_cleanup;
467  e; prev = e, e = e->next_cleanup)
468  {
469  if (e->data == data && e->data2 == data2 && e->cleanup == cleanup) {
470  prev->next_cleanup = e->next_cleanup;
471  break;
472  }
473  }
474 }
475 
476 /*
477  * Implementation of method release_debug for interface afw_pool.
478  */
479 void
480 impl_afw_pool_release_debug(
481  const afw_pool_t * instance,
482  afw_xctx_t *xctx,
483  const afw_utf8_z_t * source_z)
484 {
487 
488  IMPL_PRINT_DEBUG_INFO_Z(minimal, "afw_pool_release");
489 
490  impl_afw_pool_release(instance, xctx);
491 }
492 
493 /*
494  * Implementation of method add_reference for interface afw_pool.
495  */
496 void
497 impl_afw_pool_add_reference_debug(
498  const afw_pool_t * instance,
499  afw_xctx_t *xctx,
500  const afw_utf8_z_t * source_z)
501 {
504 
505  IMPL_PRINT_DEBUG_INFO_Z(minimal, "afw_pool_add_reference");
506 
507  impl_afw_pool_add_reference(instance, xctx);
508 }
509 
510 /*
511  * Implementation of method destroy_debug for interface afw_pool.
512  */
513 void
514 impl_afw_pool_destroy_debug(
515  const afw_pool_t * instance,
516  afw_xctx_t *xctx,
517  const afw_utf8_z_t * source_z)
518 {
521 
522  IMPL_PRINT_DEBUG_INFO_Z(minimal, "afw_pool_destroy");
523 
524  impl_afw_pool_destroy(instance, xctx);
525 }
526 
527 
528 /*
529  * Implementation of method calloc_debug for interface afw_pool.
530  */
531 void *
532 impl_afw_pool_calloc_debug(
533  const afw_pool_t * instance,
534  afw_size_t size,
535  afw_xctx_t *xctx,
536  const afw_utf8_z_t * source_z)
537 {
540 
541  IMPL_PRINT_DEBUG_INFO_FZ(detail,
542  "afw_pool_calloc %" AFW_SIZE_T_FMT,
543  size);
544 
545  return impl_afw_pool_calloc(instance, size, xctx);
546 }
547 
548 /*
549  * Implementation of method malloc_debug for interface afw_pool.
550  */
551 void *
552 impl_afw_pool_malloc_debug(
553  const afw_pool_t * instance,
554  afw_size_t size,
555  afw_xctx_t *xctx,
556  const afw_utf8_z_t * source_z)
557 {
560 
561  IMPL_PRINT_DEBUG_INFO_FZ(detail,
562  "afw_pool_malloc %" AFW_SIZE_T_FMT,
563  size);
564 
565  return impl_afw_pool_malloc(instance, size, xctx);
566 }
567 
568 /*
569  * Implementation of method free_debug for interface afw_pool.
570  */
571 void
572 impl_afw_pool_free_debug(
573  const afw_pool_t * instance,
574  void * address,
575  afw_size_t size,
576  afw_xctx_t *xctx,
577  const afw_utf8_z_t * source_z)
578 {
581 
582  IMPL_PRINT_DEBUG_INFO_FZ(detail,
583  "afw_pool_free %" AFW_SIZE_T_FMT,
584  size);
585 
586  impl_afw_pool_free(instance, address, size, xctx);
587 }
588 
589 /*
590  * Implementation of method register_cleanup_before_debug for interface
591  * afw_pool.
592  */
593 void
594 impl_afw_pool_register_cleanup_before_debug(
595  const afw_pool_t * instance,
596  void * data,
597  void * data2,
599  afw_xctx_t *xctx,
600  const afw_utf8_z_t * source_z)
601 {
604 
605  IMPL_PRINT_DEBUG_INFO_FZ(minimal,
606  "afw_pool_register_cleanup_before %p %p",
607  data, cleanup);
608 
609  impl_afw_pool_register_cleanup_before(instance, data, data2, cleanup, xctx);
610 }
611 
612 /*
613  * Implementation of method deregister_cleanup_debug for interface afw_pool.
614  */
615 void
616 impl_afw_pool_deregister_cleanup_debug(
617  const afw_pool_t * instance,
618  void * data,
619  void * data2,
621  afw_xctx_t *xctx,
622  const afw_utf8_z_t * source_z)
623 {
626 
627  IMPL_PRINT_DEBUG_INFO_FZ(minimal,
628  "afw_pool_deregister_cleanup_debug %p %p",
629  data, cleanup);
630 
631  impl_afw_pool_deregister_cleanup(instance, data, data2, cleanup, xctx);
632 }
AFW_DEFINE(const afw_object_t *)
Adaptive Framework Core Internal.
Interface afw_interface implementation declares.
afw_integer_t afw_atomic_integer_increment(AFW_ATOMIC afw_integer_t *mem)
Integer atomic increment.
Definition: afw_atomic.h:127
#define AFW_INTEGER_FMT
Format string specifier used for afw_integer_t.
Definition: afw_common.h:326
afw_utf8_octet_t afw_utf8_z_t
NFC normalized UTF-8 null terminated string.
Definition: afw_common.h:523
apr_size_t afw_size_t
size_t.
Definition: afw_common.h:151
void(* afw_pool_cleanup_function_p_t)(void *data, void *data2, const afw_pool_t *p, afw_xctx_t *xctx)
Typedef for pool cleanup functions.
Definition: afw_common.h:954
#define AFW_SIZE_T_FMT
Format string specifier used for afw_size_t.
Definition: afw_common.h:341
apr_int64_t afw_integer_t
typedef for big signed int.
Definition: afw_common.h:321
struct afw_thread_s afw_thread_t
#define AFW_THROW_ERROR_Z(code, message_z, xctx)
Macro used to set error and 0 rv in xctx and throw it.
Definition: afw_error.h:283
void impl_afw_pool_release(const afw_pool_t *instance, afw_xctx_t *xctx)
void impl_afw_pool_free(const afw_pool_t *instance, void *address, afw_size_t size, afw_xctx_t *xctx)
apr_pool_t * impl_afw_pool_get_apr_pool(const afw_pool_t *instance)
#define afw_pool_destroy(instance, xctx)
Call method destroy of interface afw_pool.
#define afw_pool_add_reference(instance, xctx)
Call method add_reference of interface afw_pool.
#define afw_pool_release(instance, xctx)
Call method release of interface afw_pool.
#define afw_pool_calloc_type(instance, type, xctx)
Macro to allocate cleared memory to hold type in pool.
Definition: afw_pool.h:167
afw_pool_create(const afw_pool_t *parent, afw_xctx_t *xctx)
Create a new pool.
afw_pool_create_debug(const afw_pool_t *parent, afw_xctx_t *xctx, const afw_utf8_z_t *source_z)
Debug version of create a new pool.
Struct for typedef afw_environment_t defined in afw_common.h.
Definition: afw_common.h:1383
Struct for registered cleanup functions.
Definition: afw_pool.h:35
afw_pool_cleanup_t * next_cleanup
Next cleanup function.
Definition: afw_pool.h:39
apr_pool_t * apr_p
Associated apr pool or NULL if it has not been created.
afw_integer_t pool_number
Unique number for pool.
afw_integer_t reference_count
Pools reference count.
Interface afw_pool public struct.
Struct for public part of afw_pool_t.
Definition: afw_thread.h:56
const afw_pool_t * p
The thread specific pool for the thread.
Definition: afw_thread.h:72
Interface afw_xctx public struct.