From 0f9bef055788c60cd4f6621a46b047abb86bc193 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Mon, 16 May 2011 16:42:35 -0600 Subject: Consolidate reference counting code. --- libdimension/Makefile.am | 2 ++ libdimension/csg.c | 2 -- libdimension/dimension.h | 1 + libdimension/dimension/interior.h | 2 +- libdimension/dimension/refcount.h | 55 +++++++++++++++++++++++++++++++++++++++ libdimension/dimension/texture.h | 4 +-- libdimension/interior.c | 17 +++++------- libdimension/object.c | 5 ++++ libdimension/refcount.c | 46 ++++++++++++++++++++++++++++++++ libdimension/texture.c | 17 +++++------- 10 files changed, 124 insertions(+), 27 deletions(-) create mode 100644 libdimension/dimension/refcount.h create mode 100644 libdimension/refcount.c diff --git a/libdimension/Makefile.am b/libdimension/Makefile.am index 3dbbbb3..e824308 100644 --- a/libdimension/Makefile.am +++ b/libdimension/Makefile.am @@ -53,6 +53,7 @@ nobase_include_HEADERS = dimension.h \ dimension/polynomial.h \ dimension/progress.h \ dimension/raytrace.h \ + dimension/refcount.h \ dimension/scene.h \ dimension/sky_sphere.h \ dimension/texture.h \ @@ -102,6 +103,7 @@ libdimension_la_SOURCES = $(nobase_include_HEADERS) \ prtree.c \ prtree.h \ raytrace.c \ + refcount.c \ reflective.c \ scene.c \ sky_sphere.c \ diff --git a/libdimension/csg.c b/libdimension/csg.c index 05f0b60..caecee0 100644 --- a/libdimension/csg.c +++ b/libdimension/csg.c @@ -32,12 +32,10 @@ dmnsn_csg_cascade(const dmnsn_object *csg, dmnsn_object *object) { if (!object->texture && csg->texture) { object->texture = csg->texture; - ++*object->texture->refcount; } if (!object->interior && csg->interior) { object->interior = csg->interior; - ++*object->interior->refcount; } object->trans = dmnsn_matrix_mul(csg->trans, object->trans); diff --git a/libdimension/dimension.h b/libdimension/dimension.h index 3f0ea57..33b8378 100644 --- a/libdimension/dimension.h +++ b/libdimension/dimension.h @@ -77,6 +77,7 @@ typedef void dmnsn_free_fn(void *ptr); #include #include #include +#include #include #include #include diff --git a/libdimension/dimension/interior.h b/libdimension/dimension/interior.h index 88af0b9..76f0a32 100644 --- a/libdimension/dimension/interior.h +++ b/libdimension/dimension/interior.h @@ -33,7 +33,7 @@ typedef struct dmnsn_interior { void *ptr; /** @internal Reference count. */ - unsigned int *refcount; + dmnsn_refcount *refcount; } dmnsn_interior; /** diff --git a/libdimension/dimension/refcount.h b/libdimension/dimension/refcount.h new file mode 100644 index 0000000..14f31ab --- /dev/null +++ b/libdimension/dimension/refcount.h @@ -0,0 +1,55 @@ +/************************************************************************* + * Copyright (C) 2011 Tavian Barnes * + * * + * This file is part of The Dimension Library. * + * * + * The Dimension 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; either version 3 of the * + * License, or (at your option) any later version. * + * * + * The Dimension Library 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 * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this program. If not, see * + * . * + *************************************************************************/ + +/** + * @file + * Generic reference count implementation. + */ + +/** + * Increment a reference count. + * @param[in,out] object The reference-counted object to acquire. + */ +#define DMNSN_INCREF(obj) ((void)++(*(obj)->refcount)) + +/** + * Decrement a reference count. + * @param[in,out] object The reference-counted object to release. + * @return Whether the object is now garbage. + */ +#define DMNSN_DECREF(obj) (*(obj)->refcount == 0 || --(*(obj)->refcount) == 0) + +/** + * Reference counter. + */ +typedef unsigned int dmnsn_refcount; + +/** + * Create a reference count. + * @return A new reference counter, initialized to zero (a "borrowed" reference, + * which will be garbage-collected the first time it is deleted). + */ +dmnsn_refcount *dmnsn_new_refcount(void); + +/** + * Delete a reference count. Raises an error if the reference count wasn't + * zero. + */ +void dmnsn_delete_refcount(dmnsn_refcount *refcount); diff --git a/libdimension/dimension/texture.h b/libdimension/dimension/texture.h index 31ab86b..8051c02 100644 --- a/libdimension/dimension/texture.h +++ b/libdimension/dimension/texture.h @@ -31,8 +31,8 @@ typedef struct { dmnsn_matrix trans; /**< Transformation matrix. */ dmnsn_matrix trans_inv; /**< The inverse of the transformation matrix. */ - unsigned int *refcount; /**< @internal Reference count. */ - bool should_init; /**< @internal Whether to initialize the texture. */ + dmnsn_refcount *refcount; /**< @internal Reference count. */ + bool should_init; /**< @internal Whether to initialize the texture. */ } dmnsn_texture; /** diff --git a/libdimension/interior.c b/libdimension/interior.c index 939bd4f..0eec274 100644 --- a/libdimension/interior.c +++ b/libdimension/interior.c @@ -33,8 +33,7 @@ dmnsn_new_interior(void) dmnsn_interior *interior = dmnsn_malloc(sizeof(dmnsn_interior)); interior->ior = 1.0; interior->free_fn = NULL; - interior->refcount = dmnsn_malloc(sizeof(unsigned int)); - *interior->refcount = 1; + interior->refcount = dmnsn_new_refcount(); return interior; } @@ -42,15 +41,11 @@ dmnsn_new_interior(void) void dmnsn_delete_interior(dmnsn_interior *interior) { - if (interior) { - if (*interior->refcount <= 1) { - if (interior->free_fn) { - interior->free_fn(interior->ptr); - } - dmnsn_free(interior->refcount); - dmnsn_free(interior); - } else { - --*interior->refcount; + if (interior && DMNSN_DECREF(interior)) { + if (interior->free_fn) { + interior->free_fn(interior->ptr); } + dmnsn_delete_refcount(interior->refcount); + dmnsn_free(interior); } } diff --git a/libdimension/object.c b/libdimension/object.c index dda80f0..7c4a714 100644 --- a/libdimension/object.c +++ b/libdimension/object.c @@ -68,10 +68,15 @@ dmnsn_initialize_object(dmnsn_object *object) bool should_init = false; dmnsn_matrix old_trans = object->trans; if (object->texture) { + DMNSN_INCREF(object->texture); should_init = object->texture->should_init; object->texture->should_init = false; } + if (object->interior) { + DMNSN_INCREF(object->interior); + } + if (object->initialize_fn) { object->initialize_fn(object); } diff --git a/libdimension/refcount.c b/libdimension/refcount.c new file mode 100644 index 0000000..66bc010 --- /dev/null +++ b/libdimension/refcount.c @@ -0,0 +1,46 @@ +/************************************************************************* + * Copyright (C) 2011 Tavian Barnes * + * * + * This file is part of The Dimension Library. * + * * + * The Dimension 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; either version 3 of the * + * License, or (at your option) any later version. * + * * + * The Dimension Library 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 * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this program. If not, see * + * . * + *************************************************************************/ + +/** + * @file + * Reference counts. + */ + +#include "dimension.h" + +dmnsn_refcount * +dmnsn_new_refcount(void) +{ + dmnsn_refcount *refcount = dmnsn_malloc(sizeof(dmnsn_refcount)); + *refcount = 0; + return refcount; +} + +void +dmnsn_delete_refcount(dmnsn_refcount *refcount) +{ + if (refcount) { + if (*refcount != 0) { + dmnsn_error("Attempt to delete non-zero reference count."); + } + + dmnsn_free(refcount); + } +} diff --git a/libdimension/texture.c b/libdimension/texture.c index d0c1944..5f3b98d 100644 --- a/libdimension/texture.c +++ b/libdimension/texture.c @@ -33,8 +33,7 @@ dmnsn_new_texture(void) texture->pigment = NULL; texture->finish = NULL; texture->trans = dmnsn_identity_matrix(); - texture->refcount = dmnsn_malloc(sizeof(unsigned int)); - *texture->refcount = 1; + texture->refcount = dmnsn_new_refcount(); texture->should_init = true; return texture; } @@ -43,15 +42,11 @@ dmnsn_new_texture(void) void dmnsn_delete_texture(dmnsn_texture *texture) { - if (texture) { - if (*texture->refcount <= 1) { - dmnsn_delete_finish(texture->finish); - dmnsn_delete_pigment(texture->pigment); - dmnsn_free(texture->refcount); - dmnsn_free(texture); - } else { - --*texture->refcount; - } + if (texture && DMNSN_DECREF(texture)) { + dmnsn_delete_finish(texture->finish); + dmnsn_delete_pigment(texture->pigment); + dmnsn_delete_refcount(texture->refcount); + dmnsn_free(texture); } } -- cgit v1.2.3