summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@gmail.com>2009-06-23 04:26:12 +0000
committerTavian Barnes <tavianator@gmail.com>2009-06-23 04:26:12 +0000
commit02d9554b1d81e1ddae04194c299b354c04b0c706 (patch)
tree073ad103b6ac71f5ec852774dae34a5b7c03592a
parentefe600537740bb572f4a062ab6b9df12623e0c24 (diff)
downloaddimension-02d9554b1d81e1ddae04194c299b354c04b0c706.tar.xz
New dmnsn_array_size() thread-safe function.
-rw-r--r--libdimension/array.c43
-rw-r--r--libdimension/dimension/array.h4
-rw-r--r--libdimension/progress.c37
-rw-r--r--libdimension/raytrace.c4
4 files changed, 61 insertions, 27 deletions
diff --git a/libdimension/array.c b/libdimension/array.c
index f0378cf..f8f3c58 100644
--- a/libdimension/array.c
+++ b/libdimension/array.c
@@ -64,15 +64,20 @@ void dmnsn_delete_array(dmnsn_array *array) {
void
dmnsn_array_push(dmnsn_array *array, const void *obj)
{
- dmnsn_array_set(array, array->length, obj);
+ dmnsn_array_wrlock(array);
+ dmnsn_array_set_impl(array, dmnsn_array_size_unlocked(array), obj);
+ dmnsn_array_unlock(array);
}
void
dmnsn_array_pop(dmnsn_array *array, void *obj)
{
+ size_t size;
+
dmnsn_array_wrlock(array);
- dmnsn_array_get_impl(array, array->length - 1, obj);
- dmnsn_array_resize_unlocked(array, array->length - 1);
+ size = dmnsn_array_size_unlocked(array);
+ dmnsn_array_get_impl(array, size - 1, obj);
+ dmnsn_array_resize_unlocked(array, size - 1);
dmnsn_array_unlock(array);
}
@@ -80,7 +85,7 @@ void
dmnsn_array_get(const dmnsn_array *array, size_t i, void *obj)
{
dmnsn_array_rdlock(array);
- dmnsn_array_get_impl(array, i, obj);
+ dmnsn_array_get_impl(array, i, obj);
dmnsn_array_unlock(array);
}
@@ -88,25 +93,43 @@ void
dmnsn_array_set(dmnsn_array *array, size_t i, const void *obj)
{
dmnsn_array_wrlock(array);
- dmnsn_array_set_impl(array, i, obj);
+ dmnsn_array_set_impl(array, i, obj);
dmnsn_array_unlock(array);
}
+size_t
+dmnsn_array_size(const dmnsn_array *array)
+{
+ size_t size;
+
+ dmnsn_array_rdlock(array);
+ size = dmnsn_array_size_unlocked(array);
+ dmnsn_array_unlock(array);
+
+ return size;
+}
+
void
dmnsn_array_resize(dmnsn_array *array, size_t length)
{
dmnsn_array_wrlock(array);
- dmnsn_array_resize_unlocked(array, length);
+ dmnsn_array_resize_unlocked(array, length);
dmnsn_array_unlock(array);
}
void *
dmnsn_array_at(dmnsn_array *array, size_t i)
{
- if (i >= array->length) {
+ if (i >= dmnsn_array_size_unlocked(array)) {
dmnsn_error(DMNSN_SEVERITY_HIGH, "Array index out of bounds.");
}
- return array->ptr + array->obj_size*i;
+ return (char *)array->ptr + array->obj_size*i;
+}
+
+size_t
+dmnsn_array_size_unlocked(const dmnsn_array *array)
+{
+ return array->length;
}
void
@@ -158,7 +181,7 @@ dmnsn_array_unlock(const dmnsn_array *array)
static void
dmnsn_array_get_impl(const dmnsn_array *array, size_t i, void *obj)
{
- if (i >= array->length) {
+ if (i >= dmnsn_array_size_unlocked(array)) {
dmnsn_error(DMNSN_SEVERITY_HIGH, "Array index out of bounds.");
}
memcpy(obj, array->ptr + array->obj_size*i, array->obj_size);
@@ -167,7 +190,7 @@ dmnsn_array_get_impl(const dmnsn_array *array, size_t i, void *obj)
static void
dmnsn_array_set_impl(dmnsn_array *array, size_t i, const void *obj)
{
- if (i >= array->length) {
+ if (i >= dmnsn_array_size_unlocked(array)) {
dmnsn_array_resize_unlocked(array, i + 1);
}
memcpy(array->ptr + array->obj_size*i, obj, array->obj_size);
diff --git a/libdimension/dimension/array.h b/libdimension/dimension/array.h
index 5abdf48..d0693fc 100644
--- a/libdimension/dimension/array.h
+++ b/libdimension/dimension/array.h
@@ -46,11 +46,13 @@ void dmnsn_array_pop(dmnsn_array *array, void *obj);
void dmnsn_array_get(const dmnsn_array *array, size_t i, void *obj);
void dmnsn_array_set(dmnsn_array *array, size_t i, const void *obj);
-void dmnsn_array_resize(dmnsn_array *array, size_t length);
+size_t dmnsn_array_size(const dmnsn_array *array);
+void dmnsn_array_resize(dmnsn_array *array, size_t length);
/* Manual locking */
void *dmnsn_array_at(dmnsn_array *array, size_t i);
+size_t dmnsn_array_size_unlocked(const dmnsn_array *array);
void dmnsn_array_resize_unlocked(dmnsn_array *array, size_t length);
void dmnsn_array_rdlock(const dmnsn_array *array);
diff --git a/libdimension/progress.c b/libdimension/progress.c
index aa6891c..dc0339c 100644
--- a/libdimension/progress.c
+++ b/libdimension/progress.c
@@ -22,6 +22,7 @@
#include <pthread.h>
#include <stdlib.h> /* For malloc */
+/* Allocate a new dmnsn_progress*, returning NULL on failure */
dmnsn_progress *
dmnsn_new_progress()
{
@@ -42,6 +43,8 @@ dmnsn_new_progress()
return progress;
}
+/* Delete a dmnsn_progress*, which has not yet been associated with a thread;
+ mostly for failed returns from *_async() functions. */
void
dmnsn_delete_progress(dmnsn_progress *progress)
{
@@ -58,6 +61,7 @@ dmnsn_delete_progress(dmnsn_progress *progress)
}
}
+/* Join the worker thread and delete `progress'. */
int dmnsn_finish_progress(dmnsn_progress *progress)
{
void *ptr;
@@ -82,25 +86,27 @@ int dmnsn_finish_progress(dmnsn_progress *progress)
return retval;
}
+/* Get the current progress of the worker thread, in [0.0, 1.0] */
double
dmnsn_get_progress(const dmnsn_progress *progress)
{
dmnsn_progress_element *element;
double prog = 0.0;
- unsigned int i;
+ unsigned int i, size;
dmnsn_array_rdlock(progress->elements);
- for (i = 0; i < progress->elements->length; ++i) {
- element = dmnsn_array_at(progress->elements,
- progress->elements->length - i - 1);
- prog += element->progress;
- prog /= element->total;
- }
+ size = dmnsn_array_size_unlocked(progress->elements);
+ for (i = 0; i < size; ++i) {
+ element = dmnsn_array_at(progress->elements, size - i - 1);
+ prog += element->progress;
+ prog /= element->total;
+ }
dmnsn_array_unlock(progress->elements);
return prog;
}
+/* A new level of algorithmic nesting */
void
dmnsn_new_progress_element(dmnsn_progress *progress, unsigned int total)
{
@@ -108,20 +114,23 @@ dmnsn_new_progress_element(dmnsn_progress *progress, unsigned int total)
dmnsn_array_push(progress->elements, &element);
}
+/* Only the innermost loop needs to call this function - it handles the rest
+ upon loop completion (progress == total) */
void
dmnsn_increment_progress(dmnsn_progress *progress)
{
dmnsn_progress_element *element;
+ size_t size;
dmnsn_array_wrlock(progress->elements);
- element = dmnsn_array_at(progress->elements, progress->elements->length - 1);
+ size = dmnsn_array_size_unlocked(progress->elements);
+ element = dmnsn_array_at(progress->elements, size - 1);
++element->progress;
- while (element->progress >= element->total
- && progress->elements->length > 1) {
- dmnsn_array_resize_unlocked(progress->elements,
- progress->elements->length - 1);
- element = dmnsn_array_at(progress->elements, progress->elements->length - 1);
+ while (element->progress >= element->total && size > 1) {
+ --size;
+ dmnsn_array_resize_unlocked(progress->elements, size);
+ element = dmnsn_array_at(progress->elements, size - 1);
++element->progress;
}
@@ -139,7 +148,7 @@ dmnsn_progress_done(dmnsn_progress *progress)
dmnsn_array_wrlock(progress->elements);
dmnsn_array_resize_unlocked(progress->elements, 1);
- element = dmnsn_array_at(progress->elements, progress->elements->length - 1);
+ element = dmnsn_array_at(progress->elements, 0);
element->progress = element->total;
if (pthread_cond_broadcast(&progress->cond) != 0) {
diff --git a/libdimension/raytrace.c b/libdimension/raytrace.c
index e91dbb2..8a01f23 100644
--- a/libdimension/raytrace.c
+++ b/libdimension/raytrace.c
@@ -88,7 +88,7 @@ dmnsn_raytrace_scene_thread(void *arg)
/* Get the ray corresponding to the (i,j)th pixel */
ray = (*scene->camera->ray_fn)(scene->camera, scene->canvas, i, j);
- for (k = 0; k < scene->objects->length; ++k) {
+ for (k = 0; k < dmnsn_array_size(scene->objects); ++k) {
dmnsn_array_get(scene->objects, k, &object);
/* Transform the ray according to the object */
@@ -96,7 +96,7 @@ dmnsn_raytrace_scene_thread(void *arg)
/* Test for intersections with objects */
intersections = (*object->intersections_fn)(object, ray_trans);
- for (l = 0; l < intersections->length; ++l) {
+ for (l = 0; l < dmnsn_array_size(intersections); ++l) {
dmnsn_array_get(intersections, l, &t_temp);
if (t_temp < t || t == 0.0) t = t_temp;
}