From a2bf45329a172d2c53594c64d27f1c15ac26796a Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Mon, 28 Feb 2011 16:28:21 -0500 Subject: New dmnsn_warning() API, remove different severities. --- libdimension/dimension/error.h | 55 ++++++++++--------------- libdimension/error.c | 93 ++++++++++++++++-------------------------- libdimension/malloc.c | 6 +-- libdimension/platform.c | 8 ++-- libdimension/profile.c | 22 +++++----- libdimension/progress.c | 47 ++++++++++----------- libdimension/raytrace.c | 2 +- libdimension/threads.c | 9 ++-- 8 files changed, 101 insertions(+), 141 deletions(-) (limited to 'libdimension') diff --git a/libdimension/dimension/error.h b/libdimension/dimension/error.h index e2fd612..db4197b 100644 --- a/libdimension/dimension/error.h +++ b/libdimension/dimension/error.h @@ -29,24 +29,21 @@ #ifndef DIMENSION_ERROR_H #define DIMENSION_ERROR_H -/** Error severity codes. */ -typedef enum dmnsn_severity { - DMNSN_SEVERITY_LOW, /**< Only die on low resilience. */ - DMNSN_SEVERITY_MEDIUM, /**< Die on low or medium resilience. */ - DMNSN_SEVERITY_HIGH /**< Always die. */ -} dmnsn_severity; +#include + +/** + * Report a warning. + * @param[in] str A string to print explaining the warning. + */ +#define dmnsn_warning(str) \ + dmnsn_report_error(false, DMNSN_FUNC, __FILE__, __LINE__, str) /** * Report an error. - * @param[in] severity A @ref dmnsn_severity representing the severity of the - * error. DMNSN_SEVERITY_HIGH will always terminate the - * running thread. * @param[in] str A string to print explaining the error. */ -#define dmnsn_error(severity, str) \ - dmnsn_report_error((dmnsn_severity)(severity), \ - DMNSN_FUNC, __FILE__, __LINE__, \ - str) +#define dmnsn_error(str) \ + dmnsn_report_error(true, DMNSN_FUNC, __FILE__, __LINE__, str) /** * @def dmnsn_assert @@ -60,36 +57,28 @@ typedef enum dmnsn_severity { #define dmnsn_assert(expr, str) \ do { \ if (!(expr)) { \ - dmnsn_error(DMNSN_SEVERITY_HIGH, (str)); \ + dmnsn_error((str)); \ } \ } while (0) #endif /** * @internal - * Called by dmnsn_error(); don't call directly. - * @param[in] severity The severity of the error. - * @param[in] func The name of the function where the error originated. - * @param[in] file The file where the error originated. - * @param[in] line The line number where the error originated. - * @param[in] str A string describing the error. - */ -void dmnsn_report_error(dmnsn_severity severity, - const char *func, const char *file, unsigned int line, - const char *str); - -/** - * Get the library resilience, thread-safely. - * @return The error severity considered fatal. + * Called by dmnsn_warning() and dmnsn_error(); don't call directly. + * @param[in] die Whether the error is fatal. + * @param[in] func The name of the function where the error originated. + * @param[in] file The file where the error originated. + * @param[in] line The line number where the error originated. + * @param[in] str A string describing the error. */ -dmnsn_severity dmnsn_get_resilience(void); +void dmnsn_report_error(bool die, const char *func, const char *file, + unsigned int line, const char *str); /** - * Set the library resilience, thread-safely. - * @param[in] resilience The new minimum severity that will cause a fatal - * error. + * Treat warnings as errors. + * @param[in] always_die Whether to die on warnings. */ -void dmnsn_set_resilience(dmnsn_severity resilience); +void dmnsn_die_on_warnings(bool always_die); /** * Fatal error callback type. This function should never return. diff --git a/libdimension/error.c b/libdimension/error.c index 974503a..b83dec4 100644 --- a/libdimension/error.c +++ b/libdimension/error.c @@ -1,5 +1,5 @@ /************************************************************************* - * Copyright (C) 2009-2010 Tavian Barnes * + * Copyright (C) 2009-2011 Tavian Barnes * * * * This file is part of The Dimension Library. * * * @@ -37,78 +37,55 @@ static dmnsn_fatal_error_fn *dmnsn_fatal = &dmnsn_default_fatal_error_fn; static pthread_mutex_t dmnsn_fatal_mutex = PTHREAD_MUTEX_INITIALIZER; /** The current resilience. */ -static dmnsn_severity dmnsn_resilience = DMNSN_SEVERITY_MEDIUM; -/** Mutex which protexts \c dmnsn_resilience. */ -static pthread_mutex_t dmnsn_resilience_mutex = PTHREAD_MUTEX_INITIALIZER; +static bool dmnsn_always_die = false; +/** Mutex which protexts \c dmnsn_always_die. */ +static pthread_mutex_t dmnsn_always_die_mutex = PTHREAD_MUTEX_INITIALIZER; -/* Called by dmnsn_error macro (don't call directly). */ +/* Called by dmnsn_error macro (don't call directly) */ void -dmnsn_report_error(dmnsn_severity severity, - const char *func, const char *file, unsigned int line, - const char *str) +dmnsn_report_error(bool die, const char *func, const char *file, + unsigned int line, const char *str) { - if (severity >= dmnsn_get_resilience()) { - /* An error more severe than our resilience happened, bail out */ - fprintf(stderr, "Dimension ERROR: %s, %s:%u: %s\n", - func, file, line, str); - dmnsn_fatal_error_fn *fatal = dmnsn_get_fatal_error_fn(); - (*fatal)(); - exit(EXIT_FAILURE); /* Failsafe in case *dmnsn_fatal doesn't exit */ - } else { - /* A trivial error happened, warn and continue */ - fprintf(stderr, "Dimension WARNING: %s, %s:%u: %s\n", - func, file, line, str); - } -} - -/* Return the current resilience, thread-safely. */ -dmnsn_severity -dmnsn_get_resilience(void) -{ - dmnsn_severity resilience; - if (pthread_mutex_lock(&dmnsn_resilience_mutex) != 0) { - /* Couldn't lock the mutex, so warn and continue. */ - fprintf(stderr, "Dimension WARNING: %s, line %u: %s\n", + if (pthread_mutex_lock(&dmnsn_always_die_mutex) != 0) { + fprintf(stderr, "Dimension ERROR: %s, line %u: %s\n", DMNSN_FUNC, __LINE__, - "Couldn't lock resilience mutex."); + "Couldn't lock mutex."); + exit(EXIT_FAILURE); } - resilience = dmnsn_resilience; /* Copy the static variable to a local */ - if (pthread_mutex_unlock(&dmnsn_resilience_mutex) != 0) { - /* Couldn't unlock the mutex, so warn and continue. If the mutex was locked - earlier, the next dmnsn_get/set_resilience is likely to hang. */ - fprintf(stderr, "Dimension WARNING: %s, line %u: %s\n", + bool always_die = dmnsn_always_die; + if (pthread_mutex_unlock(&dmnsn_always_die_mutex) != 0) { + fprintf(stderr, "Dimension ERROR: %s, line %u: %s\n", DMNSN_FUNC, __LINE__, - "Couldn't unlock resilience mutex."); + "Couldn't unlock mutex."); + exit(EXIT_FAILURE); } - return resilience; -} -/* Set the resilience, thread-safely */ -void -dmnsn_set_resilience(dmnsn_severity resilience) -{ - if (resilience < DMNSN_SEVERITY_LOW || resilience > DMNSN_SEVERITY_HIGH) { - /* Tried to set an illegal resilience, bail out */ - fprintf(stderr, "Dimension ERROR: %s, line %u: %s\n", DMNSN_FUNC, __LINE__, - "Resilience has wrong value."); + fprintf(stderr, "Dimension %s: %s, %s:%u: %s\n", + die ? "ERROR" : "WARNING", func, file, line, str); + + if (die || always_die) { + /* An error happened, bail out */ dmnsn_fatal_error_fn *fatal = dmnsn_get_fatal_error_fn(); (*fatal)(); - exit(EXIT_FAILURE); + exit(EXIT_FAILURE); /* Failsafe in case *dmnsn_fatal doesn't exit */ } +} - if (pthread_mutex_lock(&dmnsn_resilience_mutex) != 0) { - /* Couldn't lock the mutex, so warn and continue. */ - fprintf(stderr, "Dimension WARNING: %s, line %u: %s\n", +void +dmnsn_die_on_warnings(bool always_die) +{ + if (pthread_mutex_lock(&dmnsn_always_die_mutex) != 0) { + fprintf(stderr, "Dimension ERROR: %s, line %u: %s\n", DMNSN_FUNC, __LINE__, - "Couldn't lock resilience mutex."); + "Couldn't lock mutex."); + exit(EXIT_FAILURE); } - dmnsn_resilience = resilience; - if (pthread_mutex_unlock(&dmnsn_resilience_mutex) != 0) { - /* Couldn't unlock the mutex, so warn and continue. If the mutex was locked - earlier, the next dmnsn_get/set_resilience is likely to hang. */ - fprintf(stderr, "Dimension WARNING: %s, line %u: %s\n", + dmnsn_always_die = always_die; + if (pthread_mutex_unlock(&dmnsn_always_die_mutex) != 0) { + fprintf(stderr, "Dimension ERROR: %s, line %u: %s\n", DMNSN_FUNC, __LINE__, - "Couldn't unlock resilience mutex."); + "Couldn't unlock mutex."); + exit(EXIT_FAILURE); } } diff --git a/libdimension/malloc.c b/libdimension/malloc.c index f5666a0..e9dbd1e 100644 --- a/libdimension/malloc.c +++ b/libdimension/malloc.c @@ -1,5 +1,5 @@ /************************************************************************* - * Copyright (C) 2010 Tavian Barnes * + * Copyright (C) 2010-2011 Tavian Barnes * * * * This file is part of The Dimension Library. * * * @@ -32,7 +32,7 @@ dmnsn_malloc(size_t size) { void *ptr = malloc(size); if (!ptr) { - dmnsn_error(DMNSN_SEVERITY_HIGH, "Memory allocation failed."); + dmnsn_error("Memory allocation failed."); } return ptr; } @@ -42,7 +42,7 @@ dmnsn_realloc(void *ptr, size_t size) { ptr = realloc(ptr, size); if (!ptr) { - dmnsn_error(DMNSN_SEVERITY_HIGH, "Memory allocation failed."); + dmnsn_error("Memory allocation failed."); } return ptr; } diff --git a/libdimension/platform.c b/libdimension/platform.c index a678cf4..1039ac7 100644 --- a/libdimension/platform.c +++ b/libdimension/platform.c @@ -1,5 +1,5 @@ /************************************************************************* - * Copyright (C) 2010 Tavian Barnes * + * Copyright (C) 2010-2011 Tavian Barnes * * * * This file is part of The Dimension Library. * * * @@ -87,7 +87,7 @@ dmnsn_ncpus(void) if (sched_getaffinity(0, sizeof(cpuset), &cpuset) == 0) { return CPU_COUNT(&cpuset); } else { - dmnsn_error(DMNSN_SEVERITY_MEDIUM, "sched_getaffinity() failed."); + dmnsn_warning("sched_getaffinity() failed."); return 1; } #elif DMNSN_SC_NPROCESSORS_ONLN @@ -95,7 +95,7 @@ dmnsn_ncpus(void) if (nprocs > 0) { return nprocs; } else { - dmnsn_error(DMNSN_SEVERITY_MEDIUM, "sysconf(_SC_NPROCESSORS_ONLN) failed."); + dmnsn_warning("sysconf(_SC_NPROCESSORS_ONLN) failed."); return 1; } #elif defined(_WIN32) @@ -120,7 +120,7 @@ dmnsn_get_times(dmnsn_timer *timer) if (!clk_tck) { clk_tck = sysconf(_SC_CLK_TCK); if (clk_tck == -1) { - dmnsn_error(DMNSN_SEVERITY_MEDIUM, "sysconf(_SC_CLK_TCK) failed."); + dmnsn_warning("sysconf(_SC_CLK_TCK) failed."); clk_tck = 1000000L; } } diff --git a/libdimension/profile.c b/libdimension/profile.c index dd680db..cb94cc4 100644 --- a/libdimension/profile.c +++ b/libdimension/profile.c @@ -66,11 +66,11 @@ dmnsn_delete_thread_profile(void *ptr) dmnsn_dictionary *thread_profile = ptr; if (pthread_mutex_lock(&dmnsn_profile_mutex) != 0) { - dmnsn_error(DMNSN_SEVERITY_HIGH, "Couldn't lock mutex."); + dmnsn_error("Couldn't lock mutex."); } dmnsn_dictionary_apply(thread_profile, &dmnsn_profile_globalize); if (pthread_mutex_unlock(&dmnsn_profile_mutex) != 0) { - dmnsn_error(DMNSN_SEVERITY_HIGH, "Couldn't unlock mutex."); + dmnsn_error("Couldn't unlock mutex."); } dmnsn_delete_dictionary(thread_profile); @@ -84,15 +84,15 @@ dmnsn_initialize_thread_profile(void) &dmnsn_delete_thread_profile) != 0) { - dmnsn_error(DMNSN_SEVERITY_HIGH, "pthread_key_create() failed."); + dmnsn_error("pthread_key_create() failed."); } if (pthread_mutex_lock(&dmnsn_profile_mutex) != 0) { - dmnsn_error(DMNSN_SEVERITY_HIGH, "Couldn't lock mutex."); + dmnsn_error("Couldn't lock mutex."); } dmnsn_profile = dmnsn_new_dictionary(sizeof(dmnsn_branch)); if (pthread_mutex_unlock(&dmnsn_profile_mutex) != 0) { - dmnsn_error(DMNSN_SEVERITY_HIGH, "Couldn't unlock mutex."); + dmnsn_error("Couldn't unlock mutex."); } } @@ -104,7 +104,7 @@ dmnsn_get_thread_profile(void) &dmnsn_initialize_thread_profile) != 0) { - dmnsn_error(DMNSN_SEVERITY_HIGH, "pthread_once() failed."); + dmnsn_error("pthread_once() failed."); } return pthread_getspecific(dmnsn_thread_profile); @@ -115,7 +115,7 @@ static void dmnsn_set_thread_profile(dmnsn_dictionary *thread_profile) { if (pthread_setspecific(dmnsn_thread_profile, thread_profile) != 0) { - dmnsn_error(DMNSN_SEVERITY_HIGH, "pthread_setspecific() failed."); + dmnsn_error("pthread_setspecific() failed."); } } @@ -125,12 +125,12 @@ dmnsn_expect(bool result, bool expected, const char *func, const char *file, { int size = snprintf(NULL, 0, "%s:%s:%u", file, func, line) + 1; if (size < 1) { - dmnsn_error(DMNSN_SEVERITY_HIGH, "sprintf() failed."); + dmnsn_error("sprintf() failed."); } char key[size]; if (snprintf(key, size, "%s:%s:%u", file, func, line) < 0) { - dmnsn_error(DMNSN_SEVERITY_HIGH, "sprintf() failed."); + dmnsn_error("sprintf() failed."); } dmnsn_dictionary *thread_profile = dmnsn_get_thread_profile(); @@ -181,12 +181,12 @@ dmnsn_print_bad_predictions(void) } if (pthread_mutex_lock(&dmnsn_profile_mutex) != 0) { - dmnsn_error(DMNSN_SEVERITY_HIGH, "Couldn't lock mutex."); + dmnsn_error("Couldn't lock mutex."); } dmnsn_dictionary_apply(dmnsn_profile, &dmnsn_print_bad_prediction); dmnsn_delete_dictionary(dmnsn_profile); dmnsn_profile = NULL; if (pthread_mutex_unlock(&dmnsn_profile_mutex) != 0) { - dmnsn_error(DMNSN_SEVERITY_HIGH, "Couldn't unlock mutex."); + dmnsn_error("Couldn't unlock mutex."); } } diff --git a/libdimension/progress.c b/libdimension/progress.c index 99b4b3c..96940e2 100644 --- a/libdimension/progress.c +++ b/libdimension/progress.c @@ -45,17 +45,17 @@ dmnsn_new_progress(void) progress->rwlock = dmnsn_malloc(sizeof(pthread_rwlock_t)); if (pthread_rwlock_init(progress->rwlock, NULL) != 0) { - dmnsn_error(DMNSN_SEVERITY_HIGH, "Couldn't initialize read-write lock."); + dmnsn_error("Couldn't initialize read-write lock."); } progress->cond = dmnsn_malloc(sizeof(pthread_cond_t)); if (pthread_cond_init(progress->cond, NULL) != 0) { - dmnsn_error(DMNSN_SEVERITY_HIGH, "Couldn't initialize condition variable."); + dmnsn_error("Couldn't initialize condition variable."); } progress->mutex = dmnsn_malloc(sizeof(pthread_mutex_t)); if (pthread_mutex_init(progress->mutex, NULL) != 0) { - dmnsn_error(DMNSN_SEVERITY_HIGH, "Couldn't initialize mutex."); + dmnsn_error("Couldn't initialize mutex."); } progress->min_wait = 1.0; @@ -74,9 +74,7 @@ dmnsn_finish_progress(dmnsn_progress *progress) if (progress) { /* Get the thread's return value */ if (pthread_join(progress->thread, &ptr) != 0) { - /* Medium severity because an unjoined thread likely means that the thread - is incomplete or invalid */ - dmnsn_error(DMNSN_SEVERITY_MEDIUM, "Joining worker thread failed."); + dmnsn_error("Joining worker thread failed."); } else if (ptr) { retval = *(int *)ptr; dmnsn_free(ptr); @@ -84,13 +82,13 @@ dmnsn_finish_progress(dmnsn_progress *progress) /* Free the progress object */ if (pthread_rwlock_destroy(progress->rwlock) != 0) { - dmnsn_error(DMNSN_SEVERITY_LOW, "Leaking rwlock."); + dmnsn_warning("Leaking rwlock."); } if (pthread_mutex_destroy(progress->mutex) != 0) { - dmnsn_error(DMNSN_SEVERITY_LOW, "Leaking mutex."); + dmnsn_warning("Leaking mutex."); } if (pthread_cond_destroy(progress->cond) != 0) { - dmnsn_error(DMNSN_SEVERITY_LOW, "Leaking condition variable."); + dmnsn_warning("Leaking condition variable."); } dmnsn_free(progress->rwlock); dmnsn_free(progress->mutex); @@ -118,25 +116,22 @@ dmnsn_get_progress(const dmnsn_progress *progress) void dmnsn_wait_progress(const dmnsn_progress *progress, double prog) { - if (pthread_mutex_lock(progress->mutex) != 0) { - dmnsn_error(DMNSN_SEVERITY_MEDIUM, "Couldn't lock condition mutex."); - /* Busy-wait if we can't use the condition variable */ - while (dmnsn_get_progress(progress) < prog); - } else { + if (pthread_mutex_lock(progress->mutex) == 0) { while (dmnsn_get_progress(progress) < prog) { /* Set the minimum waited-on value */ if (prog < progress->min_wait) *progress->min_waitp = prog; if (pthread_cond_wait(progress->cond, progress->mutex) != 0) { - dmnsn_error(DMNSN_SEVERITY_LOW, - "Couldn't wait on condition variable."); + dmnsn_error("Couldn't wait on condition variable."); } } if (pthread_mutex_unlock(progress->mutex) != 0) { - dmnsn_error(DMNSN_SEVERITY_MEDIUM, "Couldn't unlock condition mutex."); + dmnsn_error("Couldn't unlock condition mutex."); } + } else { + dmnsn_error("Couldn't lock condition mutex."); } } @@ -158,19 +153,19 @@ dmnsn_increment_progress(dmnsn_progress *progress) dmnsn_progress_unlock(progress); if (pthread_mutex_lock(progress->mutex) != 0) { - dmnsn_error(DMNSN_SEVERITY_MEDIUM, "Couldn't lock condition mutex."); + dmnsn_error("Couldn't lock condition mutex."); } if (dmnsn_get_progress(progress) >= progress->min_wait) { progress->min_wait = 1.0; if (pthread_cond_broadcast(progress->cond) != 0) { - dmnsn_error(DMNSN_SEVERITY_MEDIUM, "Couldn't signal condition variable."); + dmnsn_error("Couldn't signal condition variable."); } } if (pthread_mutex_unlock(progress->mutex) != 0) { - dmnsn_error(DMNSN_SEVERITY_MEDIUM, "Couldn't unlock condition mutex."); + dmnsn_error("Couldn't unlock condition mutex."); } } @@ -183,13 +178,13 @@ dmnsn_done_progress(dmnsn_progress *progress) dmnsn_progress_unlock(progress); if (pthread_mutex_lock(progress->mutex) != 0) { - dmnsn_error(DMNSN_SEVERITY_MEDIUM, "Couldn't lock condition mutex."); + dmnsn_error("Couldn't lock condition mutex."); } if (pthread_cond_broadcast(progress->cond) != 0) { - dmnsn_error(DMNSN_SEVERITY_MEDIUM, "Couldn't signal condition variable."); + dmnsn_error("Couldn't signal condition variable."); } if (pthread_mutex_unlock(progress->mutex) != 0) { - dmnsn_error(DMNSN_SEVERITY_MEDIUM, "Couldn't unlock condition mutex."); + dmnsn_error("Couldn't unlock condition mutex."); } } @@ -199,7 +194,7 @@ static void dmnsn_progress_rdlock(const dmnsn_progress *progress) { if (pthread_rwlock_rdlock(progress->rwlock) != 0) { - dmnsn_error(DMNSN_SEVERITY_MEDIUM, "Couldn't acquire read-lock."); + dmnsn_error("Couldn't acquire read-lock."); } } @@ -207,7 +202,7 @@ static void dmnsn_progress_wrlock(dmnsn_progress *progress) { if (pthread_rwlock_wrlock(progress->rwlock) != 0) { - dmnsn_error(DMNSN_SEVERITY_MEDIUM, "Couldn't acquire write-lock."); + dmnsn_error("Couldn't acquire write-lock."); } } @@ -215,6 +210,6 @@ static void dmnsn_progress_unlock(const dmnsn_progress *progress) { if (pthread_rwlock_unlock(progress->rwlock) != 0) { - dmnsn_error(DMNSN_SEVERITY_MEDIUM, "Couldn't unlock read-write lock."); + dmnsn_error("Couldn't unlock read-write lock."); } } diff --git a/libdimension/raytrace.c b/libdimension/raytrace.c index 4e762f3..9a3b323 100644 --- a/libdimension/raytrace.c +++ b/libdimension/raytrace.c @@ -43,7 +43,7 @@ dmnsn_raytrace_scene(dmnsn_scene *scene) { dmnsn_progress *progress = dmnsn_raytrace_scene_async(scene); if (dmnsn_finish_progress(progress) != 0) { - dmnsn_error(DMNSN_SEVERITY_HIGH, "Error occured while raytracing."); + dmnsn_error("Error occured while raytracing."); } } diff --git a/libdimension/threads.c b/libdimension/threads.c index 35127ac..fc05ac7 100644 --- a/libdimension/threads.c +++ b/libdimension/threads.c @@ -1,5 +1,5 @@ /************************************************************************* - * Copyright (C) 2010 Tavian Barnes * + * Copyright (C) 2010-2011 Tavian Barnes * * * * This file is part of The Dimension Library. * * * @@ -68,7 +68,7 @@ dmnsn_new_thread(dmnsn_progress *progress, dmnsn_thread_fn *thread_fn, payload->progress = progress; if (pthread_create(&progress->thread, NULL, &dmnsn_thread, payload) != 0) { - dmnsn_error(DMNSN_SEVERITY_HIGH, "Couldn't start thread."); + dmnsn_error("Couldn't start thread."); } } @@ -104,7 +104,7 @@ dmnsn_execute_concurrently(dmnsn_concurrent_thread_fn *thread_fn, if (pthread_create(&threads[i], NULL, &dmnsn_concurrent_thread, &payloads[i]) != 0) { - dmnsn_error(DMNSN_SEVERITY_HIGH, "Couldn't start worker thread."); + dmnsn_error("Couldn't start worker thread."); } } @@ -115,8 +115,7 @@ dmnsn_execute_concurrently(dmnsn_concurrent_thread_fn *thread_fn, ret = payloads[i].ret; } } else { - dmnsn_error(DMNSN_SEVERITY_MEDIUM, "Couldn't join worker thread."); - ret = -1; + dmnsn_error("Couldn't join worker thread."); } } -- cgit v1.2.3