X-Git-Url: http://git.onelab.eu/?p=libnl.git;a=blobdiff_plain;f=lib%2Fobject.c;fp=lib%2Fobject.c;h=80f40471174a08d47b3e7eabe6d115f35bb8a988;hp=0000000000000000000000000000000000000000;hb=4cee2ecb3b8afa0637e6f5fe4c57985a4bc740ff;hpb=2df2fbe518d5a221ce6e3ee88a3fb23fb1b94b27 diff --git a/lib/object.c b/lib/object.c new file mode 100644 index 0000000..80f4047 --- /dev/null +++ b/lib/object.c @@ -0,0 +1,285 @@ +/* + * lib/object.c Generic Cacheable Object + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2003-2006 Thomas Graf + */ + +/** + * @ingroup cache + * @defgroup object Cacheable Object + * @{ + */ + +#include +#include +#include +#include +#include + +static inline struct nl_cache_ops *obj_ops(struct nl_object *obj) +{ + if (!obj->ce_ops) + BUG(); + + return obj->ce_ops; +} + +/** + * @name Object Creation/Deletion + * @{ + */ + +/** + * Allocate a cacheable object + * @arg size size of object + * @return The new object or NULL. + */ +struct nl_object *nl_object_alloc(size_t size) +{ + struct nl_object *new; + + if (size < sizeof(*new)) + BUG(); + + new = calloc(1, size); + if (!new) { + nl_errno(ENOMEM); + return NULL; + } + + new->ce_refcnt = 1; + nl_init_list_head(&new->ce_list); + + return new; +} + +/** + * Allocate a new object of kind specified by the operations handle + * @arg ops cache operations handle + * @return The new object or NULL + */ +struct nl_object *nl_object_alloc_from_ops(struct nl_cache_ops *ops) +{ + struct nl_object *new; + + new = nl_object_alloc(ops->co_size); + if (new) { + new->ce_ops = ops; + if (ops->co_constructor) + ops->co_constructor(new); + } + + return new; +} + +/** + * Allocate a new object of kind specified by the name + * @arg kind name of object type + * @return The new object or nULL + */ +struct nl_object *nl_object_alloc_name(const char *kind) +{ + struct nl_cache_ops *ops; + + ops = nl_cache_mngt_lookup(kind); + if (!ops) { + nl_error(ENOENT, "Unable to lookup cache kind \"%s\"", kind); + return NULL; + } + + return nl_object_alloc_from_ops(ops); +} + +struct nl_derived_object { + NLHDR_COMMON + char data; +}; + +/** + * Allocate a new object and copy all data from an existing object + * @arg obj object to inherite data from + * @return The new object or NULL. + */ +struct nl_object *nl_object_clone(struct nl_object *obj) +{ + struct nl_object *new; + struct nl_cache_ops *ops = obj_ops(obj); + int doff = offsetof(struct nl_derived_object, data); + int size; + + new = nl_object_alloc(ops->co_size); + if (!new) + return NULL; + + size = ops->co_size - doff; + if (size < 0) + BUG(); + + new->ce_cache = obj->ce_cache; + new->ce_ops = obj->ce_ops; + new->ce_msgtype = obj->ce_msgtype; + if (ops->co_free_data) { + new->ce_dataref = obj; + nl_object_get(obj); + } + + if (size) + memcpy((void *)new + doff, (void *)obj + doff, size); + + return new; +} + +/** + * Free a cacheable object + * @arg obj object to free + * + * @return 0 or a negative error code. + */ +void nl_object_free(struct nl_object *obj) +{ + struct nl_cache_ops *ops = obj_ops(obj); + + if (obj->ce_refcnt > 0) + NL_DBG(1, "Warning: Freeing object in used...\n"); + + if (obj->ce_dataref) + nl_object_put(obj->ce_dataref); + else if (ops->co_free_data) + ops->co_free_data(obj); + + free(obj); +} + +/** @} */ + +/** + * @name Reference Management + * @{ + */ + +/** + * Acquire a reference on a object + * @arg obj object to acquire reference from + */ +void nl_object_get(struct nl_object *obj) +{ + obj->ce_refcnt++; +} + +/** + * Release a reference from an object + * @arg obj object to release reference from + */ +void nl_object_put(struct nl_object *obj) +{ + if (!obj) + return; + + obj->ce_refcnt--; + + if (obj->ce_refcnt < 0) + BUG(); + + if (obj->ce_refcnt <= 0) + nl_object_free(obj); +} + +/** + * Check whether this object is used by multiple users + * @arg obj object to check + * @return true or false + */ +int nl_object_shared(struct nl_object *obj) +{ + return obj->ce_refcnt > 1; +} + +/** @} */ + +/** + * @name Utillities + * @{ + */ + +/** + * Dump this object according to the specified parameters + * @arg obj object to dump + * @arg params dumping parameters + */ +void nl_object_dump(struct nl_object *obj, struct nl_dump_params *params) +{ + dump_from_ops(obj, params); +} + +/** + * Match a filter against an object + * @arg obj object to check + * @arg filter filter object + * + * @return 0 if the object matches the filter or non-zero + * if no filter procedure is available or if the + * filter does not match. + */ +int nl_object_match(struct nl_object *obj, struct nl_object *filter) +{ + struct nl_cache_ops *ops = obj->ce_ops; + + if (ops == filter->ce_ops && + ops->co_filter && !ops->co_filter(obj, filter)) + return 1; + else + return 0; +} + +/** @} */ + +/** + * @name Access Functions + * @{ + */ + +/** + * Get reference count of object + * @arg obj object handle + */ +int nl_object_get_refcnt(struct nl_object *obj) +{ + return obj->ce_refcnt; +} + +/** + * Get cache operations of object + * @arg obj object handle + */ +struct nl_cache_ops *nl_object_get_ops(struct nl_object *obj) +{ + return obj->ce_ops; +} + +/** + * Get cache this object is in + * @arg obj object handle + * @return cache handle or NULL if object is not associated to a cache + */ +struct nl_cache *nl_object_get_cache(struct nl_object *obj) +{ + return obj->ce_cache; +} + +/** + * Get the private data of object + * @arg obj object handle + */ +inline void *nl_object_priv(struct nl_object *obj) +{ + return obj; +} + +/** @} */ + +/** @} */