/usr/include/nih/alloc.h is in libnih-dev 1.0.3-6ubuntu2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 | /* libnih
*
* Copyright © 2009 Scott James Remnant <scott@netsplit.com>.
* Copyright © 2009 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2, as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef NIH_ALLOC_H
#define NIH_ALLOC_H
/**
* All functions in libnih use these functions to allocate and destroy
* objects in memory, they wrap the usual malloc(), realloc() and free()
* calls to provide a multi-reference hierarchial allocator.
*
* When you allocate an object using nih_alloc() or nih_new(), you pass
* an optional parent. This may be any other object allocated with these
* functions. A reference from the parent to the newly allocated object
* is created. If no parent is passed the object is referenced from the
* special NULL parent.
*
* You may add additional references to the object using nih_ref(), again
* passing any other object allocated with these functions as the parent
* or the special NULL parent.
*
* Thus any object may have one or more parents. Indeed, an object
* (including the NULL parent) may hold multiple references to another
* object.
*
* When an object is freed, the references to its children are discarded
* and if it held the last reference to one of those children, the child
* is freed as well.
*
* This takes away a lof the effort of object management; allocating the
* members of a structure with the structure as a parent means that if you
* free the structure, all of its members will be freed as well.
*
* You may still need to do additional clean-up, for example closing file
* descriptors or other non-allocated resources. You can set a destructor
* function for the object with nih_alloc_set_destructor(), this is called
* during the free process.
*
* To remove a reference to a child, potentially freeing it but without
* freeing the parent object, use nih_unref().
*
* To free a top-level object, use nih_free(). nih_free() always frees the
* object, even if it has parent references which it will discard. This
* obviously does not clean up any pointers in the parent object which
* point at the freed child.
*
* In many situations, you will allocate an object using nih_alloc() with
* no parent and pass that to functions which may take a reference to it.
* When finished, you need to discard the object safely; if no references
* were taken, it should be freed - otherwise it's safe to leave. Use
* nih_discard() instead of nih_free() to do this.
*
* Such constructs are often better handled using nih_local variables.
*
*
* = Common patterns =
*
* At first, it seems like there's a bewildering array of different ways
* you can shoot yourself in the foot with this library, however if you
* stick to the usual patterns it's a very safe and versatile library.
*
* == Structures ==
*
* When allocating structures, you tend to write your function so that
* the prospective parent is passed in as the first argument and always
* allocate with that.
*
* obj = nih_new (parent, Object);
*
* That way, the caller decides how they want your object linked to
* other things. If there's an error while populating the structure,
* the standard style is just to call nih_free() rather than
* unreferencing
*
* error:
* nih_free (obj);
* return NULL;
*
* Since you're putting it together, this use of nih_free() is perfectly
* acceptable.
*
* == Structure members ==
*
* Structure members are just about always allocated with the structure
* as their parent context.
*
* obj->child = nih_new (obj, Child);
*
* This pretty much saves you from ever worrying about them, as they
* will be automatically freed whenever you free the parent object;
* including error handling cases.
*
* Should you ever replace the child, you shouldn't call nih_free() but
* nih_unref(), to be safe against other code having taken a reference.
*
* nih_unref (obj->child, obj);
* obj->child = nih_new (obj, Child);
*
* This will clean up the child, unless someone else is using it.
*
* == Floating objects ==
*
* Often in a function you'll want to allocate an object but won't yet
* have anything to attach it to. This also often applies to global
* variables as well.
*
* You simply pass NULL in as the parent; the returned object has only
* this special reference.
*
* obj = nih_new (NULL, Object);
*
* To discard the floating object you should use nih_discard() instead
* of nih_free(), which will not free the object if another function
* you've called in the meantime took a reference to it.
*
* Better yet, use nih_local to have the object automatically discarded
* when it goes out of scope:
*
* {
* nih_local Object *obj = NULL;
* obj = nih_new (NULL, Object);
*
* // work with obj, including passing it to functions that may
* // reference it
* }
*
* == Taking a reference ==
*
* Provided the above patterns are followed, taking a reference to an
* object you are passed is perfectly safe. Simply call nih_ref(),
* for example to store it in your own structure:
*
* adopt->obj = obj;
* nih_ref (adopt->obj, adopt);
*
* When you want to drop your reference, you should only ever use
* nih_unref().
*
* nih_unref (adopt->obj, adopt);
* adopt->obj = NULL;
*
* == Returning a member ==
*
* This is a relatively rare case, but examples exist.
*
* Sometimes you want to provide a function that returns one of your
* structure members, disowning it in the process. Your function will
* most likely take a parent object to which you want to reparent the
* member.
*
* This is as easy as referencing the new parent and dropping your own
* reference.
*
* nih_ref (child, parent);
*
* child = obj->child;
* obj->child = NULL;
*
* nih_unref (obj->child, obj);
*
* // child may now be returned
*
* == Worker objects ==
*
* Finally another pattern exits in the nih_alloc() world that doesn't
* quite obey the above rules, and instead takes advantage of the design
* to provide something that wouldn't be possible otherwise.
*
* A worker is an object that performs some function out-of-band on
* behalf of another object. They may be stored elsewhere, such as a
* linked list, and will be set up such that if they are freed, the
* work they are doing is cancelled.
*
* A good example would be a timer object; you'd have a list of timers
* which you iterate in the main loop. The destructor of the timer
* object removes it from this list. When the timer expires, some
* work occurs, and the timer object frees itself.
*
* Thus to attach a timer to our object, all we need do is create the
* timer with our object as a parent. There is absolutely no need
* to store the timer as a structure member, unless we would need to
* cancel it for other reasons.
*
* If our object is freed, the timer is freed to so there's no danger
* of the callback firing and acting on a freed object. If the timer
* fires, the callback can do its work, and the timer will be freed
* afterwards.
*
* Much of the main loop related objects in libnih behave in this way.
**/
#include <nih/macros.h>
/**
* NihDestructor:
* @ptr: pointer to be destroyed.
*
* A destructor is a function that can be associated with an allocated
* object in memory and is called before the object is freed. The pointer
* @ptr passed to the destructor is that of the object being freed.
*
* A typical use of a destructor would be to close a file descriptor held
* by an object.
*
* When the destructor is called, the parent references to the object will
* have already been discarded but all children references will be intact
* and none of the children will have been freed. There is no need to use
* a destructor to unreference or free children, that is automatic.
*
* Returns: value returned by nih_free() or nih_discard() if used directly
* on the object.
**/
typedef int (*NihDestructor) (void *ptr);
/**
* nih_new:
* @parent: parent object for new object,
* @type: type of data to store.
*
* Allocates an object in memory large enough to store a @type object
* and returns a pointer to it.
*
* If @parent is not NULL, it should be a pointer to another object which
* will be used as a parent for the returned object otherwise the special
* NULL parent will be used instead. When all parents of the returned
* object are freed, the returned object will also be freed.
*
* If you have clean-up that you would like to run, you can assign a
* destructor using the nih_alloc_set_destructor() function.
*
* Returns: newly allocated object or NULL if insufficient memory.
**/
#define nih_new(parent, type) (type *)nih_alloc(parent, sizeof (type))
/**
* nih_alloc_set_destructor:
* @ptr: pointer to object,
* @destructor: destructor function to set.
*
* Sets the destructor of the allocated object @ptr to @destructor, which
* may be NULL to unset an existing destructor. This is a macro that casts
* @destructor to the NihDestructor type, since almost all destructors
* will be defined with their argument to be the type of the object
* rather than void *.
*
* The destructor will be called before the object is freed, either
* explicitly by nih_free() or nih_discard(), or because the last parent
* has unreferenced the object.
*
* When the destructor is called, the parent references to the object will
* have already been discarded but all children references will be intact
* and none of the children will have been freed. There is no need to use
* a destructor to unreference or free children, that is automatic.
*
* The pointer @ptr passed to the destructor is that of the object being
* freed, and the destructor may return a value which will be the return
* value of nih_free() or nih_discard() if used directly on the object.
*
* Since objects may also be freed by unreferencing, and the value is not
* returned in this case, it should only be used for informational or
* debugging purposes.
**/
#define nih_alloc_set_destructor(ptr, destructor) \
nih_alloc_real_set_destructor (ptr, (NihDestructor)destructor)
/**
* nih_local:
*
* This macro may be used in a variable definition when the variable
* should be automatically cleaned up when it goes out of scope. You
* should ensure that the pointer is either allocated with nih_alloc()
* or set to NULL;
*
* {
* nih_local char *foo = NULL;
*
* foo = nih_strdup (NULL, "some data");
* } // foo is automatically discarded
*
* It is permissible to take references to foo within its scope, or by
* functions called, in which case it will not be freed. Also it is
* generally nonsensical to allocate with a parent, since this too will
* prevent it from being freed.
**/
#define nih_local __attribute__ ((cleanup(_nih_discard_local)))
NIH_BEGIN_EXTERN
void * nih_alloc (const void *parent, size_t size)
__attribute__ ((warn_unused_result));
void * nih_realloc (void *ptr, const void *parent,
size_t size)
__attribute__ ((warn_unused_result));
int nih_free (void *ptr);
int nih_discard (void *ptr);
void _nih_discard_local (void *ptraddr);
void nih_alloc_real_set_destructor (const void *ptr,
NihDestructor destructor);
void nih_ref (const void *ptr, const void *parent);
void nih_unref (void *ptr, const void *parent);
int nih_alloc_parent (const void *ptr, const void *parent);
size_t nih_alloc_size (const void *ptr);
NIH_END_EXTERN
#endif /* NIH_ALLOC_H */
|