dead.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. /**
  2. * @file dead.h
  3. * @author Ambroz Bizjak <ambrop7@gmail.com>
  4. *
  5. * @section LICENSE
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. Neither the name of the author nor the
  15. * names of its contributors may be used to endorse or promote products
  16. * derived from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  19. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  22. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  24. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  25. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  27. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. *
  29. * @section DESCRIPTION
  30. *
  31. * Dead mechanism definitions.
  32. *
  33. * The dead mechanism is a way for a piece of code to detect whether some
  34. * specific event has occured during some operation (usually during calling
  35. * a user-provided handler function), without requiring access to memory
  36. * that might no longer be available because of the event.
  37. *
  38. * It works somehow like that:
  39. *
  40. * First a dead variable ({@link dead_t}) is allocated somewhere, and
  41. * initialized with {@link DEAD_INIT}, e.g.:
  42. * DEAD_INIT(dead);
  43. *
  44. * When the event that needs to be caught occurs, {@link DEAD_KILL} is
  45. * called, e.g.:
  46. * DEAD_KILL(dead);
  47. * The memory used by the dead variable is no longer needed after
  48. * that.
  49. *
  50. * If a piece of code needs to know whether the event occured during some
  51. * operation (but it must not have occured before!), it puts {@link DEAD_ENTER}}
  52. * in front of the operation, and does {@link DEAD_LEAVE} at the end. If
  53. * {@link DEAD_LEAVE} returned nonzero, the event occured, otherwise it did
  54. * not. Example:
  55. * DEAD_ENTER(dead)
  56. * HandlerFunction();
  57. * if (DEAD_LEAVE(dead)) {
  58. * (event occured)
  59. * }
  60. *
  61. * If is is needed to check for the event more than once in a single block,
  62. * {@link DEAD_DECLARE} should be put somewhere before, and {@link DEAD_ENTER2}
  63. * should be used instead of {@link DEAD_ENTER}.
  64. *
  65. * If it is needed to check for multiple events (dead variables) at the same
  66. * time, DEAD_*_N macros should be used instead, specifying different
  67. * identiers as the first argument for different dead variables.
  68. */
  69. #ifndef BADVPN_MISC_DEAD_H
  70. #define BADVPN_MISC_DEAD_H
  71. #include <stdlib.h>
  72. /**
  73. * Dead variable.
  74. */
  75. typedef int *dead_t;
  76. /**
  77. * Initializes a dead variable.
  78. */
  79. #define DEAD_INIT(ptr) { ptr = NULL; }
  80. /**
  81. * Kills the dead variable,
  82. */
  83. #define DEAD_KILL(ptr) { if (ptr) *(ptr) = 1; }
  84. /**
  85. * Kills the dead variable with the given value, or does nothing
  86. * if the value is 0. The value will seen by {@link DEAD_KILLED}.
  87. */
  88. #define DEAD_KILL_WITH(ptr, val) { if (ptr) *(ptr) = (val); }
  89. /**
  90. * Declares dead catching variables.
  91. */
  92. #define DEAD_DECLARE int __dead; dead_t __prev_ptr;
  93. /**
  94. * Enters a dead catching using already declared dead catching variables.
  95. * The dead variable must have been initialized with {@link DEAD_INIT},
  96. * and {@link DEAD_KILL} must not have been called yet.
  97. * {@link DEAD_LEAVE2} must be called before the current scope is left.
  98. */
  99. #define DEAD_ENTER2(ptr) { __dead = 0; __prev_ptr = ptr; ptr = &__dead; }
  100. /**
  101. * Declares dead catching variables and enters a dead catching.
  102. * The dead variable must have been initialized with {@link DEAD_INIT},
  103. * and {@link DEAD_KILL} must not have been called yet.
  104. * {@link DEAD_LEAVE2} must be called before the current scope is left.
  105. */
  106. #define DEAD_ENTER(ptr) DEAD_DECLARE DEAD_ENTER2(ptr)
  107. /**
  108. * Leaves a dead catching.
  109. */
  110. #define DEAD_LEAVE2(ptr) { if (!__dead) ptr = __prev_ptr; if (__prev_ptr) *__prev_ptr = __dead; }
  111. /**
  112. * Returns 1 if {@link DEAD_KILL} was called for the dead variable, 0 otherwise.
  113. * Must be called after entering a dead catching.
  114. */
  115. #define DEAD_KILLED (__dead)
  116. #define DEAD_DECLARE_N(n) int __dead##n; dead_t __prev_ptr##n;
  117. #define DEAD_ENTER2_N(n, ptr) { __dead##n = 0; __prev_ptr##n = ptr; ptr = &__dead##n;}
  118. #define DEAD_ENTER_N(n, ptr) DEAD_DECLARE_N(n) DEAD_ENTER2_N(n, ptr)
  119. #define DEAD_LEAVE2_N(n, ptr) { if (!__dead##n) ptr = __prev_ptr##n; if (__prev_ptr##n) *__prev_ptr##n = __dead##n; }
  120. #define DEAD_KILLED_N(n) (__dead##n)
  121. #endif