summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libdimension/png.c4
-rw-r--r--libdimension/progress-impl.h12
-rw-r--r--libdimension/progress.c78
-rw-r--r--libdimension/raytrace.c3
4 files changed, 24 insertions, 73 deletions
diff --git a/libdimension/png.c b/libdimension/png.c
index 5fe51ed..9095178 100644
--- a/libdimension/png.c
+++ b/libdimension/png.c
@@ -198,7 +198,7 @@ dmnsn_png_write_canvas_thread(void *ptr)
png_uint_32 width = payload->canvas->width;
png_uint_32 height = payload->canvas->height;
- dmnsn_new_progress_element(payload->progress, height);
+ dmnsn_set_progress_total(payload->progress, height);
png_structp png_ptr
= png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
@@ -398,7 +398,7 @@ dmnsn_png_read_canvas_thread(void *ptr)
&interlace_type, &compression_type, &filter_method);
int number_of_passes = png_set_interlace_handling(png_ptr);
- dmnsn_new_progress_element(payload->progress, (number_of_passes + 1)*height);
+ dmnsn_set_progress_total(payload->progress, (number_of_passes + 1)*height);
png_set_read_status_fn(png_ptr, &dmnsn_png_read_row_callback);
/*
diff --git a/libdimension/progress-impl.h b/libdimension/progress-impl.h
index e9bfac6..87ad6c2 100644
--- a/libdimension/progress-impl.h
+++ b/libdimension/progress-impl.h
@@ -31,18 +31,16 @@
/** Allocate a new progress object. */
dmnsn_progress *dmnsn_new_progress(void);
-/** Create a new level of loop nesting. */
-void dmnsn_new_progress_element(dmnsn_progress *progress, unsigned int total);
-/** Increment the progress counter; should only be called from the innermost
- loop. */
+/** Set the total number of loop iterations. */
+void dmnsn_set_progress_total(dmnsn_progress *progress, size_t total);
+/** Increment the progress counter. */
void dmnsn_increment_progress(dmnsn_progress *progress);
/** Instantly complete the progress. */
void dmnsn_done_progress(dmnsn_progress *progress);
struct dmnsn_progress {
- /* Array of progress elements. Progress is given by P(0), where
- P(i) = (elements[i].progress + P(i + 1))/elements[i].total. */
- dmnsn_array *elements;
+ size_t progress; /**< Completed loop iterations. */
+ size_t total; /**< Total expected loop iterations. */
/* The worker thread */
pthread_t thread;
diff --git a/libdimension/progress.c b/libdimension/progress.c
index aeecbe4..098bbfb 100644
--- a/libdimension/progress.c
+++ b/libdimension/progress.c
@@ -26,40 +26,20 @@
#include "dimension-impl.h"
#include <pthread.h>
-/** A single element in an array for dmnsn_progress. Progress of this item is
- \p progress/\p total. */
-typedef struct {
- unsigned int progress, total;
-} dmnsn_progress_element;
-
/** Read-lock a progress object. */
-static void dmnsn_progress_rdlock_impl(const dmnsn_progress *progress);
+static void dmnsn_progress_rdlock(const dmnsn_progress *progress);
/** Write-lock a progress object. */
-static void dmnsn_progress_wrlock_impl(dmnsn_progress *progress);
-/** Unlock a progress object. */
-static void dmnsn_progress_unlock_impl(void *arg);
-
-/** Read-lock a progress object and ensure that it will unlock upon error. */
-#define dmnsn_progress_rdlock(progress) \
- dmnsn_progress_rdlock_impl(progress); \
- pthread_cleanup_push(&dmnsn_progress_unlock_impl, (void *)progress);
-/** Write-lock a progress object and ensure that it will unlock upon error. */
-#define dmnsn_progress_wrlock(progress) \
- dmnsn_progress_wrlock_impl(progress); \
- pthread_cleanup_push(&dmnsn_progress_unlock_impl, (void *)progress);
+static void dmnsn_progress_wrlock(dmnsn_progress *progress);
/** Unlock a progress object. */
-#define dmnsn_progress_unlock(progress) \
- pthread_cleanup_pop(1);
+static void dmnsn_progress_unlock(const dmnsn_progress *progress);
/* Allocate a new dmnsn_progress* */
dmnsn_progress *
dmnsn_new_progress(void)
{
dmnsn_progress *progress = dmnsn_malloc(sizeof(dmnsn_progress));
- progress->elements = dmnsn_new_array(sizeof(dmnsn_progress_element));
-
- dmnsn_progress_element element = { .progress = 0, .total = 1 };
- dmnsn_array_push(progress->elements, &element);
+ progress->progress = 0;
+ progress->total = 1;
/* Initialize the rwlock, condition variable, and mutex */
@@ -115,7 +95,6 @@ dmnsn_finish_progress(dmnsn_progress *progress)
dmnsn_free(progress->rwlock);
dmnsn_free(progress->mutex);
dmnsn_free(progress->cond);
- dmnsn_delete_array(progress->elements);
dmnsn_free(progress);
}
@@ -126,16 +105,10 @@ dmnsn_finish_progress(dmnsn_progress *progress)
double
dmnsn_get_progress(const dmnsn_progress *progress)
{
- dmnsn_progress_element *element;
- double prog = 0.0;
+ double prog;
dmnsn_progress_rdlock(progress);
- size_t size = dmnsn_array_size(progress->elements);
- for (size_t i = 0; i < size; ++i) {
- element = dmnsn_array_at(progress->elements, size - i - 1);
- prog += element->progress;
- prog /= element->total;
- }
+ prog = (double)progress->progress/progress->total;
dmnsn_progress_unlock(progress);
return prog;
@@ -167,35 +140,21 @@ dmnsn_wait_progress(const dmnsn_progress *progress, double prog)
}
}
-/* Start a new level of algorithmic nesting */
+/* Set the total number of loop iterations */
void
-dmnsn_new_progress_element(dmnsn_progress *progress, unsigned int total)
+dmnsn_set_progress_total(dmnsn_progress *progress, size_t total)
{
- dmnsn_progress_element element = { .progress = 0, .total = total };
dmnsn_progress_wrlock(progress);
- dmnsn_array_push(progress->elements, &element);
+ progress->total = total;
dmnsn_progress_unlock(progress);
}
-/* Only the innermost loop needs to call this function - it handles the rest
- upon loop completion (progress == total) */
+/* Increment the number of completed loop iterations */
void
dmnsn_increment_progress(dmnsn_progress *progress)
{
- dmnsn_progress_element *element;
-
dmnsn_progress_wrlock(progress);
- size_t size = dmnsn_array_size(progress->elements);
- element = dmnsn_array_at(progress->elements, size - 1);
- ++element->progress; /* Increment the last element */
-
- while (element->progress >= element->total && size > 1) {
- /* As long as the last element is complete, pop it */
- --size;
- dmnsn_array_resize(progress->elements, size);
- element = dmnsn_array_at(progress->elements, size - 1);
- ++element->progress; /* Increment the next element */
- }
+ ++progress->progress;
dmnsn_progress_unlock(progress);
if (pthread_mutex_lock(progress->mutex) != 0) {
@@ -219,12 +178,8 @@ dmnsn_increment_progress(dmnsn_progress *progress)
void
dmnsn_done_progress(dmnsn_progress *progress)
{
- dmnsn_progress_element *element;
-
dmnsn_progress_wrlock(progress);
- dmnsn_array_resize(progress->elements, 1);
- element = dmnsn_array_at(progress->elements, 0);
- element->progress = element->total;
+ progress->progress = progress->total;
dmnsn_progress_unlock(progress);
if (pthread_mutex_lock(progress->mutex) != 0) {
@@ -241,7 +196,7 @@ dmnsn_done_progress(dmnsn_progress *progress)
/* Thread synchronization */
static void
-dmnsn_progress_rdlock_impl(const dmnsn_progress *progress)
+dmnsn_progress_rdlock(const dmnsn_progress *progress)
{
if (pthread_rwlock_rdlock(progress->rwlock) != 0) {
dmnsn_error(DMNSN_SEVERITY_MEDIUM, "Couldn't acquire read-lock.");
@@ -249,7 +204,7 @@ dmnsn_progress_rdlock_impl(const dmnsn_progress *progress)
}
static void
-dmnsn_progress_wrlock_impl(dmnsn_progress *progress)
+dmnsn_progress_wrlock(dmnsn_progress *progress)
{
if (pthread_rwlock_wrlock(progress->rwlock) != 0) {
dmnsn_error(DMNSN_SEVERITY_MEDIUM, "Couldn't acquire write-lock.");
@@ -257,9 +212,8 @@ dmnsn_progress_wrlock_impl(dmnsn_progress *progress)
}
static void
-dmnsn_progress_unlock_impl(void *arg)
+dmnsn_progress_unlock(const dmnsn_progress *progress)
{
- const dmnsn_progress *progress = arg;
if (pthread_rwlock_unlock(progress->rwlock) != 0) {
dmnsn_error(DMNSN_SEVERITY_MEDIUM, "Couldn't unlock read-write lock.");
}
diff --git a/libdimension/raytrace.c b/libdimension/raytrace.c
index c91b74c..691ce83 100644
--- a/libdimension/raytrace.c
+++ b/libdimension/raytrace.c
@@ -97,8 +97,7 @@ dmnsn_raytrace_scene_thread(void *ptr)
threads = dmnsn_malloc(nthreads*sizeof(pthread_t));
/* Set up the progress object */
- dmnsn_new_progress_element(payload->progress,
- payload->scene->canvas->height);
+ dmnsn_set_progress_total(payload->progress, payload->scene->canvas->height);
/* Create the payloads */
for (int i = 0; i < nthreads; ++i) {