diff options
-rw-r--r-- | libdimension/png.c | 4 | ||||
-rw-r--r-- | libdimension/progress-impl.h | 12 | ||||
-rw-r--r-- | libdimension/progress.c | 78 | ||||
-rw-r--r-- | libdimension/raytrace.c | 3 |
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) { |