object.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  3. * Copyright (C) 2005 Red Hat, Inc.
  4. * All rights reserved.
  5. *
  6. * License: GPL (version 3 or any later version).
  7. * See LICENSE for details.
  8. * END COPYRIGHT BLOCK **/
  9. #ifdef HAVE_CONFIG_H
  10. # include <config.h>
  11. #endif
  12. /* Implementation note:
  13. PR_AtomicIncrement and PR_AtomicDecrement both return a value whose
  14. sign is the same sign (or zero) as the variable *after* it was updated.
  15. They do not return the previous value.
  16. */
  17. #include "slapi-plugin.h"
  18. #include "slapi-private.h"
  19. typedef struct object
  20. {
  21. PRInt32 refcnt; /* reference count for the object */
  22. FNFree destructor; /* Destructor for the object */
  23. void *data; /* pointer to actual node data */
  24. } object;
  25. /*
  26. * Create a new object.
  27. * The object is created with refcnt set to 1. The caller implicitly gets
  28. * a reference to the object, to prevent a race condition where the object
  29. * is destroyed immediately after contruction.
  30. * The provided destructor function will be called when all references to
  31. * the object have been released.
  32. *
  33. * Returns a pointer to the new object.
  34. */
  35. Object *
  36. object_new(void *user_data, FNFree destructor)
  37. {
  38. Object *o;
  39. o = (object *)slapi_ch_malloc(sizeof(object));
  40. o->refcnt = 1;
  41. o->destructor = destructor;
  42. o->data = user_data;
  43. return o;
  44. }
  45. /*
  46. * Acquire a reference object. The caller must hold a reference
  47. * to the object, or know for certain that a reference is held
  48. * and will continue to be held while this call is in progress.
  49. */
  50. void
  51. object_acquire(Object *o)
  52. {
  53. PR_ASSERT(NULL != o);
  54. PR_AtomicIncrement(&o->refcnt);
  55. }
  56. /*
  57. * Release a reference to an object. The pointer to the object
  58. * should not be referenced after this call is made, since the
  59. * object may be destroyed if this is the last reference to it.
  60. */
  61. void
  62. object_release(Object *o)
  63. {
  64. PRInt32 refcnt_after_release;
  65. PR_ASSERT(NULL != o);
  66. refcnt_after_release = PR_AtomicDecrement(&o->refcnt);
  67. PR_ASSERT(refcnt_after_release >= 0);
  68. if (refcnt_after_release == 0)
  69. {
  70. /* Object can be destroyed */
  71. if (o->destructor)
  72. o->destructor(&o->data);
  73. /* Make it harder to reuse a dangling pointer */
  74. o->data = NULL;
  75. o->destructor = NULL;
  76. o->refcnt = -9999;
  77. slapi_ch_free((void **)&o);
  78. }
  79. }
  80. /*
  81. * Get the data pointer from an object.
  82. * Results are undefined if the caller does not hold a reference
  83. * to the object.
  84. */
  85. void *
  86. object_get_data(Object *o)
  87. {
  88. PR_ASSERT(NULL != o);
  89. return o->data;
  90. }