fix typo
[tor.git] / src / common / handles.h
blob6d7262ab8016f75b2624005ef0b7bd1959fe5c74
1 /* Copyright (c) 2016-2017, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
4 /**
5 * \file handles.h
6 * \brief Macros for C weak-handle implementation.
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".
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.
16 * To enable a type to have handles, add a HANDLE_ENTRY() field in its
17 * definition, as in:
19 * struct walrus {
20 * HANDLE_ENTRY(wlr, walrus);
21 * // ...
22 * };
24 * And invoke HANDLE_DECL(wlr, walrus, [static]) to declare the handle
25 * manipulation functions (typically in a header):
27 * // opaque handle to walrus.
28 * typedef struct wlr_handle_t wlr_handle_t;
30 * // make a new handle
31 * struct wlr_handle_t *wlr_handle_new(struct walrus *);
33 * // release a handle
34 * void wlr_handle_free(wlr_handle_t *);
36 * // return the pointed-to walrus, or NULL.
37 * struct walrus *wlr_handle_get(wlr_handle_t *).
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 *);
44 * Finally, use HANDLE_IMPL() to define the above functions in some
45 * appropriate C file: HANDLE_IMPL(wlr, walrus, [static])
47 **/
49 #ifndef TOR_HANDLE_H
50 #define TOR_HANDLE_H
52 #include "orconfig.h"
53 #include "tor_queue.h"
54 #include "util.h"
56 #define HANDLE_ENTRY(name, structname) \
57 struct name ## _handle_head_t *handle_head
59 #define HANDLE_DECL(name, structname, linkage) \
60 typedef struct name ## _handle_t name ## _handle_t; \
61 linkage name ## _handle_t *name ## _handle_new(struct structname *object); \
62 linkage void name ## _handle_free(name ## _handle_t *); \
63 linkage struct structname *name ## _handle_get(name ## _handle_t *); \
64 linkage void name ## _handles_clear(struct structname *object);
67 * Implementation notes: there are lots of possible implementations here. We
68 * could keep a linked list of handles, each with a backpointer to the object,
69 * and set all of their backpointers to NULL when the object is freed. Or we
70 * could have the clear function invalidate the object, but not actually let
71 * the object get freed until the all the handles went away. We could even
72 * have a hash-table mapping unique identifiers to objects, and have each
73 * handle be a copy of the unique identifier. (We'll want to build that last
74 * one eventually if we want cross-process handles.)
76 * But instead we're opting for a single independent 'head' that knows how
77 * many handles there are, and where the object is (or isn't). This makes
78 * all of our functions O(1), and most as fast as a single pointer access.
80 * The handles themselves are opaque structures holding a pointer to the head.
81 * We could instead have each foo_handle_t* be identical to foo_handle_head_t
82 * *, and save some allocations ... but doing so would make handle leaks
83 * harder to debug. As it stands, every handle leak is a memory leak, and
84 * existing memory debugging tools should help with those. We can revisit
85 * this decision if handles are too slow.
88 #define HANDLE_IMPL(name, structname, linkage) \
89 /* The 'head' object for a handle-accessible type. This object */ \
90 /* persists for as long as the object, or any handles, exist. */ \
91 typedef struct name ## _handle_head_t { \
92 struct structname *object; /* pointed-to object, or NULL */ \
93 unsigned int references; /* number of existing handles */ \
94 } name ## _handle_head_t; \
96 struct name ## _handle_t { \
97 struct name ## _handle_head_t *head; /* reference to the 'head'. */ \
98 }; \
100 linkage struct name ## _handle_t * \
101 name ## _handle_new(struct structname *object) \
103 tor_assert(object); \
104 name ## _handle_head_t *head = object->handle_head; \
105 if (PREDICT_UNLIKELY(head == NULL)) { \
106 head = object->handle_head = tor_malloc_zero(sizeof(*head)); \
107 head->object = object; \
109 name ## _handle_t *new_ref = tor_malloc_zero(sizeof(*new_ref)); \
110 new_ref->head = head; \
111 ++head->references; \
112 return new_ref; \
115 linkage void \
116 name ## _handle_free(struct name ## _handle_t *ref) \
118 if (! ref) return; \
119 name ## _handle_head_t *head = ref->head; \
120 tor_assert(head); \
121 --head->references; \
122 tor_free(ref); \
123 if (head->object == NULL && head->references == 0) { \
124 tor_free(head); \
125 return; \
129 linkage struct structname * \
130 name ## _handle_get(struct name ## _handle_t *ref) \
132 tor_assert(ref); \
133 name ## _handle_head_t *head = ref->head; \
134 tor_assert(head); \
135 return head->object; \
138 linkage void \
139 name ## _handles_clear(struct structname *object) \
141 tor_assert(object); \
142 name ## _handle_head_t *head = object->handle_head; \
143 if (! head) \
144 return; \
145 object->handle_head = NULL; \
146 head->object = NULL; \
147 if (head->references == 0) { \
148 tor_free(head); \
152 #endif /* TOR_HANDLE_H */