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.

ref.h 2.2KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. /*-
  2. * Copyright 2016 Vsevolod Stakhov
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #ifndef REF_H_
  17. #define REF_H_
  18. #ifdef HAVE_CONFIG_H
  19. #include "config.h"
  20. #endif
  21. /**
  22. * @file ref.h
  23. * A set of macros to handle refcounts
  24. */
  25. typedef void (*ref_dtor_cb_t)(void *data);
  26. typedef struct ref_entry_s {
  27. unsigned int refcount;
  28. ref_dtor_cb_t dtor;
  29. } ref_entry_t;
  30. #define REF_INIT(obj, dtor_cb) do { \
  31. if ((obj) != NULL) { \
  32. (obj)->ref.refcount = 0; \
  33. (obj)->ref.dtor = (ref_dtor_cb_t)(dtor_cb); \
  34. } \
  35. } while (0)
  36. #define REF_INIT_RETAIN(obj, dtor_cb) do { \
  37. if ((obj) != NULL) { \
  38. (obj)->ref.refcount = 1; \
  39. (obj)->ref.dtor = (ref_dtor_cb_t)(dtor_cb); \
  40. } \
  41. } while (0)
  42. #ifdef HAVE_ATOMIC_BUILTINS
  43. #define REF_RETAIN_ATOMIC(obj) do { \
  44. if ((obj) != NULL) { \
  45. __atomic_add_fetch (&(obj)->ref.refcount, 1, __ATOMIC_RELEASE); \
  46. } \
  47. } while (0)
  48. #define REF_RELEASE_ATOMIC(obj) do { \
  49. if ((obj) != NULL) { \
  50. unsigned int _rc_priv = __atomic_sub_fetch (&(obj)->ref.refcount, 1, __ATOMIC_ACQ_REL); \
  51. if (_rc_priv == 0 && (obj)->ref.dtor) { \
  52. (obj)->ref.dtor (obj); \
  53. } \
  54. } \
  55. } while (0)
  56. #else
  57. #define REF_RETAIN_ATOMIC REF_RETAIN
  58. #define REF_RELEASE_ATOMIC REF_RELEASE_ATOMIC
  59. #endif
  60. #define REF_RETAIN(obj) do { \
  61. if ((obj) != NULL) { \
  62. (obj)->ref.refcount ++; \
  63. } \
  64. } while (0)
  65. #define REF_RELEASE(obj) do { \
  66. if ((obj) != NULL) { \
  67. if (--(obj)->ref.refcount == 0 && (obj)->ref.dtor) { \
  68. (obj)->ref.dtor (obj); \
  69. } \
  70. } \
  71. } while (0)
  72. #endif /* REF_H_ */