| /* libnih |
| * |
| * Copyright © 2009 Scott James Remnant <scott@netsplit.com>. |
| * Copyright © 2009 Canonical Ltd. |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining |
| * a copy of this software and associated documentation files (the |
| * "Software"), to deal in the Software without restriction, including |
| * without limitation the rights to use, copy, modify, merge, publish, |
| * distribute, sublicense, and/or sell copies of the Software, and to |
| * permit persons to whom the Software is furnished to do so, subject to |
| * the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be |
| * included in all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
| * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR |
| * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF |
| * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
| * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| */ |
| |
| #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. |
| * |
| * You may add additional references to the object using nih_ref(), again |
| * passing any other object allocated with these functions are the parent. |
| * |
| * Thus any object may have zero or more parents. |
| * |
| * 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. But what if there's an error while populating the |
| * structure? You can't call nih_unref() because that won't accept |
| * NULL as the parent, and you can't call nih_discard() because that |
| * won't work if there is a parent. |
| * |
| * You might be tempted to call one or the other depending on whether |
| * parent is NULL or not, however it's by far better style to just call |
| * nih_free() |
| * |
| * 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 no |
| * references, and is known as a floating object. |
| * |
| * obj = nih_new (NULL, Object); |
| * |
| * If anything takes a reference to this, it will no longer be floating |
| * and will instead be referenced. Should that reference be dropped, |
| * obj will be freed. |
| * |
| * 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. |
| * |
| * It's not quite as easy as referencing the parent and dropping your |
| * own reference, because the parent could be NULL. And if you did |
| * that, and held the last reference on the member, it would be freed |
| * before returning. |
| * |
| * Instead use nih_unref_only(), which may leave the object floating |
| * |
| * nih_unref_only (obj->child, obj); |
| * |
| * child = obj->child; |
| * obj->child = NULL; |
| * |
| * if (parent) |
| * nih_ref (child, parent); |
| * |
| * // 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. 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 beign 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, malloc)); |
| |
| void * nih_realloc (void *ptr, const void *parent, |
| size_t size) |
| __attribute__ ((warn_unused_result, malloc)); |
| |
| 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); |
| void nih_unref_only (const 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 */ |