diff options
Diffstat (limited to 'intern/clog/clog.c')
-rw-r--r-- | intern/clog/clog.c | 103 |
1 files changed, 96 insertions, 7 deletions
diff --git a/intern/clog/clog.c b/intern/clog/clog.c index 571177ad1d3..4bc277f8ef2 100644 --- a/intern/clog/clog.c +++ b/intern/clog/clog.c @@ -14,8 +14,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -/** \file clog/clog.c - * \ingroup clog +/** \file + * \ingroup clog */ #include <stdarg.h> @@ -24,14 +24,29 @@ #include <stdint.h> #include <assert.h> +/* Disable for small single threaded programs + * to avoid having to link with pthreads. */ +#ifdef WITH_CLOG_PTHREADS +# include <pthread.h> +# include "atomic_ops.h" +#endif + /* For 'isatty' to check for color. */ #if defined(__unix__) || defined(__APPLE__) || defined(__HAIKU__) # include <unistd.h> +# include <sys/time.h> #endif #if defined(_MSC_VER) # include <io.h> +# include <windows.h> #endif + +/* For printing timestamp. */ +#define __STDC_FORMAT_MACROS +#include <inttypes.h> + + /* Only other dependency (could use regular malloc too). */ #include "MEM_guardedalloc.h" @@ -61,15 +76,23 @@ typedef struct CLG_IDFilter { typedef struct CLogContext { /** Single linked list of types. */ CLG_LogType *types; +#ifdef WITH_CLOG_PTHREADS + pthread_mutex_t types_lock; +#endif + /* exclude, include filters. */ CLG_IDFilter *filters[2]; bool use_color; bool use_basename; + bool use_timestamp; /** Borrowed, not owned. */ int output; FILE *output_file; + /** For timer (use_timestamp). */ + uint64_t timestamp_tick_start; + /** For new types. */ struct { int level; @@ -342,12 +365,35 @@ static void clg_ctx_backtrace(CLogContext *ctx) fflush(ctx->output_file); } +static uint64_t clg_timestamp_ticks_get(void) +{ + uint64_t tick; +#if defined(_MSC_VER) + tick = GetTickCount64(); +#else + struct timeval tv; + gettimeofday(&tv, NULL); + tick = tv.tv_sec * 1000 + tv.tv_usec / 1000; +#endif + return tick; +} + /** \} */ /* -------------------------------------------------------------------- */ /** \name Logging API * \{ */ +static void write_timestamp(CLogStringBuf *cstr, const uint64_t timestamp_tick_start) +{ + char timestamp_str[64]; + const uint64_t timestamp = clg_timestamp_ticks_get() - timestamp_tick_start; + const uint timestamp_len = snprintf( + timestamp_str, sizeof(timestamp_str), "%" PRIu64 ".%03u ", + timestamp / 1000, (uint)(timestamp % 1000)); + clg_str_append_with_len(cstr, timestamp_str, timestamp_len); +} + static void write_severity(CLogStringBuf *cstr, enum CLG_Severity severity, bool use_color) { assert((unsigned int)severity < CLG_SEVERITY_LEN); @@ -399,6 +445,10 @@ void CLG_log_str( char cstr_stack_buf[CLOG_BUF_LEN_INIT]; clg_str_init(&cstr, cstr_stack_buf, sizeof(cstr_stack_buf)); + if (lg->ctx->use_timestamp) { + write_timestamp(&cstr, lg->ctx->timestamp_tick_start); + } + write_severity(&cstr, severity, lg->ctx->use_color); write_type(&cstr, lg); @@ -409,7 +459,8 @@ void CLG_log_str( clg_str_append(&cstr, "\n"); /* could be optional */ - write(lg->ctx->output, cstr.data, cstr.len); + int bytes_written = write(lg->ctx->output, cstr.data, cstr.len); + (void)bytes_written; clg_str_free(&cstr); @@ -430,6 +481,10 @@ void CLG_logf( char cstr_stack_buf[CLOG_BUF_LEN_INIT]; clg_str_init(&cstr, cstr_stack_buf, sizeof(cstr_stack_buf)); + if (lg->ctx->use_timestamp) { + write_timestamp(&cstr, lg->ctx->timestamp_tick_start); + } + write_severity(&cstr, severity, lg->ctx->use_color); write_type(&cstr, lg); @@ -444,7 +499,8 @@ void CLG_logf( clg_str_append(&cstr, "\n"); /* could be optional */ - write(lg->ctx->output, cstr.data, cstr.len); + int bytes_written = write(lg->ctx->output, cstr.data, cstr.len); + (void)bytes_written; clg_str_free(&cstr); @@ -477,6 +533,14 @@ static void CLG_ctx_output_use_basename_set(CLogContext *ctx, int value) ctx->use_basename = (bool)value; } +static void CLG_ctx_output_use_timestamp_set(CLogContext *ctx, int value) +{ + ctx->use_timestamp = (bool)value; + if (ctx->use_timestamp) { + ctx->timestamp_tick_start = clg_timestamp_ticks_get(); + } +} + /** Action on fatal severity. */ static void CLG_ctx_fatal_fn_set(CLogContext *ctx, void (*fatal_fn)(void *file_handle)) { @@ -521,6 +585,9 @@ static void CLG_ctx_level_set(CLogContext *ctx, int level) static CLogContext *CLG_ctx_init(void) { CLogContext *ctx = MEM_callocN(sizeof(*ctx), __func__); +#ifdef WITH_CLOG_PTHREADS + pthread_mutex_init(&ctx->types_lock, NULL); +#endif ctx->use_color = true; ctx->default_type.level = 1; CLG_ctx_output_set(ctx, stdout); @@ -543,6 +610,9 @@ static void CLG_ctx_free(CLogContext *ctx) MEM_freeN(item); } } +#ifdef WITH_CLOG_PTHREADS + pthread_mutex_destroy(&ctx->types_lock); +#endif MEM_freeN(ctx); } @@ -579,6 +649,10 @@ void CLG_output_use_basename_set(int value) CLG_ctx_output_use_basename_set(g_ctx, value); } +void CLG_output_use_timestamp_set(int value) +{ + CLG_ctx_output_use_timestamp_set(g_ctx, value); +} void CLG_fatal_fn_set(void (*fatal_fn)(void *file_handle)) { @@ -615,9 +689,24 @@ void CLG_level_set(int level) void CLG_logref_init(CLG_LogRef *clg_ref) { - assert(clg_ref->type == NULL); - CLG_LogType *clg_ty = clg_ctx_type_find_by_name(g_ctx, clg_ref->identifier); - clg_ref->type = clg_ty ? clg_ty : clg_ctx_type_register(g_ctx, clg_ref->identifier); +#ifdef WITH_CLOG_PTHREADS + /* Only runs once when initializing a static type in most cases. */ + pthread_mutex_lock(&g_ctx->types_lock); +#endif + if (clg_ref->type == NULL) { + CLG_LogType *clg_ty = clg_ctx_type_find_by_name(g_ctx, clg_ref->identifier); + if (clg_ty == NULL) { + clg_ty = clg_ctx_type_register(g_ctx, clg_ref->identifier); + } +#ifdef WITH_CLOG_PTHREADS + atomic_cas_ptr((void **)&clg_ref->type, clg_ref->type, clg_ty); +#else + clg_ref->type = clg_ty; +#endif + } +#ifdef WITH_CLOG_PTHREADS + pthread_mutex_unlock(&g_ctx->types_lock); +#endif } /** \} */ |