summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@gmail.com>2011-05-16 16:42:35 -0600
committerTavian Barnes <tavianator@gmail.com>2011-05-16 16:42:35 -0600
commit0f9bef055788c60cd4f6621a46b047abb86bc193 (patch)
tree2d97e7d7ead0f9f2c545c800c9789b30070b3aa6
parent0a51cc868eafe72a98d64e48d8b2ba30a7d8f5dc (diff)
downloaddimension-0f9bef055788c60cd4f6621a46b047abb86bc193.tar.xz
Consolidate reference counting code.
-rw-r--r--libdimension/Makefile.am2
-rw-r--r--libdimension/csg.c2
-rw-r--r--libdimension/dimension.h1
-rw-r--r--libdimension/dimension/interior.h2
-rw-r--r--libdimension/dimension/refcount.h55
-rw-r--r--libdimension/dimension/texture.h4
-rw-r--r--libdimension/interior.c17
-rw-r--r--libdimension/object.c5
-rw-r--r--libdimension/refcount.c46
-rw-r--r--libdimension/texture.c17
10 files changed, 124 insertions, 27 deletions
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 <dimension/inline.h>
#include <dimension/error.h>
#include <dimension/malloc.h>
+#include <dimension/refcount.h>
#include <dimension/array.h>
#include <dimension/dictionary.h>
#include <dimension/progress.h>
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 <tavianator@tavianator.com> *
+ * *
+ * 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 *
+ * <http://www.gnu.org/licenses/>. *
+ *************************************************************************/
+
+/**
+ * @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 <tavianator@tavianator.com> *
+ * *
+ * 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 *
+ * <http://www.gnu.org/licenses/>. *
+ *************************************************************************/
+
+/**
+ * @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);
}
}