You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

111 lines
3.0 KiB

10 years ago
  1. /* -*- coding: utf-8 -*-
  2. * ----------------------------------------------------------------------
  3. * Copyright © 2013, RedJack, LLC.
  4. * All rights reserved.
  5. *
  6. * Please see the COPYING file in this distribution for license
  7. * details.
  8. * ----------------------------------------------------------------------
  9. */
  10. #include <stdlib.h>
  11. #include "libcork/core.h"
  12. #include "libcork/ds.h"
  13. #include "libcork/os/process.h"
  14. #include "libcork/helpers/errors.h"
  15. #if !defined(CORK_DEBUG_PROCESS)
  16. #define CORK_DEBUG_PROCESS 0
  17. #endif
  18. #if CORK_DEBUG_PROCESS
  19. #include <stdio.h>
  20. #define DEBUG(...) fprintf(stderr, __VA_ARGS__)
  21. #else
  22. #define DEBUG(...) /* no debug messages */
  23. #endif
  24. struct cork_cleanup_entry {
  25. struct cork_dllist_item item;
  26. int priority;
  27. const char *name;
  28. cork_cleanup_function function;
  29. };
  30. static struct cork_cleanup_entry *
  31. cork_cleanup_entry_new(const char *name, int priority,
  32. cork_cleanup_function function)
  33. {
  34. struct cork_cleanup_entry *self = cork_new(struct cork_cleanup_entry);
  35. self->priority = priority;
  36. self->name = cork_strdup(name);
  37. self->function = function;
  38. return self;
  39. }
  40. static void
  41. cork_cleanup_entry_free(struct cork_cleanup_entry *self)
  42. {
  43. cork_strfree(self->name);
  44. free(self);
  45. }
  46. static struct cork_dllist cleanup_entries = CORK_DLLIST_INIT(cleanup_entries);
  47. static void
  48. cork_cleanup_entry_add(struct cork_cleanup_entry *entry)
  49. {
  50. struct cork_dllist_item *curr;
  51. /* Linear search through the list of existing cleanup functions. When we
  52. * find the first existing function with a higher priority, we've found
  53. * where to insert the new function. */
  54. for (curr = cork_dllist_start(&cleanup_entries);
  55. !cork_dllist_is_end(&cleanup_entries, curr); curr = curr->next) {
  56. struct cork_cleanup_entry *existing =
  57. cork_container_of(curr, struct cork_cleanup_entry, item);
  58. if (existing->priority > entry->priority) {
  59. cork_dllist_add_before(&existing->item, &entry->item);
  60. return;
  61. }
  62. }
  63. /* If we fall through the loop, then the new function should be appended to
  64. * the end of the list. */
  65. cork_dllist_add(&cleanup_entries, &entry->item);
  66. }
  67. static void
  68. cork_cleanup_call_one(struct cork_dllist_item *item, void *user_data)
  69. {
  70. struct cork_cleanup_entry *entry =
  71. cork_container_of(item, struct cork_cleanup_entry, item);
  72. DEBUG("Call cleanup function [%d] %s\n", entry->priority, entry->name);
  73. entry->function();
  74. cork_cleanup_entry_free(entry);
  75. }
  76. static void
  77. cork_cleanup_call_all(void)
  78. {
  79. cork_dllist_map(&cleanup_entries, cork_cleanup_call_one, NULL);
  80. }
  81. CORK_INITIALIZER(cleanup_init)
  82. {
  83. atexit(cork_cleanup_call_all);
  84. }
  85. CORK_API void
  86. cork_cleanup_at_exit_named(const char *name, int priority,
  87. cork_cleanup_function function)
  88. {
  89. struct cork_cleanup_entry *entry =
  90. cork_cleanup_entry_new(name, priority, function);
  91. DEBUG("Register cleanup function [%d] %s\n", priority, name);
  92. cork_cleanup_entry_add(entry);
  93. }