Tor  0.4.7.0-alpha-dev
handles.h
Go to the documentation of this file.
1 /* Copyright (c) 2016-2021, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
3 
4 /**
5  * \file handles.h
6  * \brief Macros for C weak-handle implementation.
7  *
8  * A 'handle' is a pointer to an object that is allowed to go away while
9  * the handle stays alive. When you dereference the handle, you might get
10  * the object, or you might get "NULL".
11  *
12  * Use this pattern when an object has a single obvious lifespan, so you don't
13  * want to use reference counting, but when other objects might need to refer
14  * to the first object without caring about its lifetime.
15  *
16  * To enable a type to have handles, add a HANDLE_ENTRY() field in its
17  * definition, as in:
18  *
19  * struct walrus_t {
20  * HANDLE_ENTRY(wlr, walrus_t);
21  * // ...
22  * };
23  *
24  * And invoke HANDLE_DECL(wlr, walrus_t, [static]) to declare the handle
25  * manipulation functions (typically in a header):
26  *
27  * // opaque handle to walrus.
28  * typedef struct wlr_handle_t wlr_handle_t;
29  *
30  * // make a new handle
31  * struct wlr_handle_t *wlr_handle_new(struct walrus_t *);
32  *
33  * // release a handle
34  * void wlr_handle_free(wlr_handle_t *);
35  *
36  * // return the pointed-to walrus, or NULL.
37  * struct walrus_t *wlr_handle_get(wlr_handle_t *).
38  *
39  * // call this function when you're about to free the walrus;
40  * // it invalidates all handles. (IF YOU DON'T, YOU WILL HAVE
41  * // DANGLING REFERENCES)
42  * void wlr_handles_clear(struct walrus_t *);
43  *
44  * Finally, use HANDLE_IMPL() to define the above functions in some
45  * appropriate C file: HANDLE_IMPL(wlr, walrus_t, [static])
46  *
47  **/
48 
49 #ifndef TOR_HANDLE_H
50 #define TOR_HANDLE_H
51 
52 #include "orconfig.h"
53 
54 #include "lib/log/util_bug.h"
55 #include "lib/malloc/malloc.h"
56 
57 #define HANDLE_ENTRY(name, structname) \
58  struct name ## _handle_head_t *handle_head
59 
60 #define HANDLE_DECL(name, structname_t, linkage) \
61  typedef struct name ## _handle_t name ## _handle_t; \
62  linkage name ## _handle_t *name ## _handle_new( \
63  struct structname_t *object); \
64  linkage void name ## _handle_free_(name ## _handle_t *); \
65  linkage struct structname_t *name ## _handle_get(name ## _handle_t *); \
66  linkage void name ## _handles_clear(struct structname_t *object);
67 
68 /*
69  * Implementation notes: there are lots of possible implementations here. We
70  * could keep a linked list of handles, each with a backpointer to the object,
71  * and set all of their backpointers to NULL when the object is freed. Or we
72  * could have the clear function invalidate the object, but not actually let
73  * the object get freed until the all the handles went away. We could even
74  * have a hash-table mapping unique identifiers to objects, and have each
75  * handle be a copy of the unique identifier. (We'll want to build that last
76  * one eventually if we want cross-process handles.)
77  *
78  * But instead we're opting for a single independent 'head' that knows how
79  * many handles there are, and where the object is (or isn't). This makes
80  * all of our functions O(1), and most as fast as a single pointer access.
81  *
82  * The handles themselves are opaque structures holding a pointer to the head.
83  * We could instead have each foo_handle_t* be identical to foo_handle_head_t
84  * *, and save some allocations ... but doing so would make handle leaks
85  * harder to debug. As it stands, every handle leak is a memory leak, and
86  * existing memory debugging tools should help with those. We can revisit
87  * this decision if handles are too slow.
88  */
89 
90 #define HANDLE_IMPL(name, structname, linkage) \
91  /* The 'head' object for a handle-accessible type. This object */ \
92  /* persists for as long as the object, or any handles, exist. */ \
93  typedef struct name ## _handle_head_t { \
94  struct structname *object; /* pointed-to object, or NULL */ \
95  unsigned int references; /* number of existing handles */ \
96  } name ## _handle_head_t; \
97  \
98  struct name ## _handle_t { \
99  struct name ## _handle_head_t *head; /* reference to the 'head'. */ \
100  }; \
101  \
102  linkage struct name ## _handle_t * \
103  name ## _handle_new(struct structname *object) \
104  { \
105  tor_assert(object); \
106  name ## _handle_head_t *head = object->handle_head; \
107  if (PREDICT_UNLIKELY(head == NULL)) { \
108  head = object->handle_head = tor_malloc_zero(sizeof(*head)); \
109  head->object = object; \
110  } \
111  name ## _handle_t *new_ref = tor_malloc_zero(sizeof(*new_ref)); \
112  new_ref->head = head; \
113  ++head->references; \
114  return new_ref; \
115  } \
116  \
117  linkage void \
118  name ## _handle_free_(struct name ## _handle_t *ref) \
119  { \
120  if (! ref) return; \
121  name ## _handle_head_t *head = ref->head; \
122  tor_assert(head); \
123  --head->references; \
124  tor_free(ref); \
125  if (head->object == NULL && head->references == 0) { \
126  tor_free(head); \
127  return; \
128  } \
129  } \
130  \
131  linkage struct structname * \
132  name ## _handle_get(struct name ## _handle_t *ref) \
133  { \
134  tor_assert(ref); \
135  name ## _handle_head_t *head = ref->head; \
136  tor_assert(head); \
137  return head->object; \
138  } \
139  \
140  linkage void \
141  name ## _handles_clear(struct structname *object) \
142  { \
143  tor_assert(object); \
144  name ## _handle_head_t *head = object->handle_head; \
145  if (! head) \
146  return; \
147  object->handle_head = NULL; \
148  head->object = NULL; \
149  if (head->references == 0) { \
150  tor_free(head); \
151  } \
152  }
153 
154 #endif /* !defined(TOR_HANDLE_H) */
Headers for util_malloc.c.
Macros to manage assertions, fatal and non-fatal.