Add cfutimer which uses more accurate functions if available

This is some code I had previously written, adapted to (mostly)
libcfu coding style. The API is very similar to that of the
existing (to be eventually removed) cfutime.
This commit is contained in:
Matthew Brush 2013-03-04 19:22:48 -08:00
parent d35b0f5b20
commit b82a8f4ec6
8 changed files with 161 additions and 7 deletions

View File

@ -27,6 +27,12 @@ AC_FUNC_MALLOC
AC_FUNC_MEMCMP AC_FUNC_MEMCMP
AC_CHECK_FUNCS([gettimeofday memset snprintf strcasecmp strncasecmp vsnprintf]) AC_CHECK_FUNCS([gettimeofday memset snprintf strcasecmp strncasecmp vsnprintf])
# Check for clock_gettime()
AC_CHECK_FUNCS([clock_gettime], [],
[AC_CHECK_LIB([rt], [clock_gettime],
[AC_DEFINE(HAVE_CLOCK_GETTIME, 1)
AC_SUBST([REALTIME_LIBS], [-lrt])])])
# Check for pthread support # Check for pthread support
AC_CHECK_LIB([pthread], AC_CHECK_LIB([pthread],
[pthread_create], [pthread_create],

View File

@ -2,4 +2,4 @@ noinst_PROGRAMS = hash_usage large_hash strings conf_example \
conf_example2 opt_example conf_example2 opt_example
AM_CFLAGS = -I$(top_srcdir)/src AM_CFLAGS = -I$(top_srcdir)/src
LDADD = $(top_builddir)/src/libcfu.la @PTHREAD_LIBS@ LDADD = $(top_builddir)/src/libcfu.la @PTHREAD_LIBS@ @REALTIME_LIBS@

View File

@ -6,5 +6,5 @@ includedir=@includedir@
Name: @PACKAGE_NAME@ Name: @PACKAGE_NAME@
Description: Portable C data structure and utility library Description: Portable C data structure and utility library
Version: @PACKAGE_VERSION@ Version: @PACKAGE_VERSION@
Libs.private: @PTHREAD_LIBS@ Libs.private: @PTHREAD_LIBS@ @REALTIME_LIBS@
Cflags: -I${includedir}/cfu Cflags: -I${includedir}/cfu

View File

@ -1,12 +1,13 @@
lib_LTLIBRARIES = libcfu.la lib_LTLIBRARIES = libcfu.la
libcfu_la_SOURCES = cfuhash.c cfutime.c cfustring.c cfulist.c \ libcfu_la_SOURCES = cfuhash.c cfutime.c cfutimer.c cfustring.c \
cfuconf.c cfu.c cfuopt.c snprintf.c cfulist.c cfuconf.c cfu.c cfuopt.c snprintf.c
libcfu_la_LIBADD = @PTHREAD_LIBS@ @REALTIME_LIBS@
libcfuincdir = $(includedir)/cfu libcfuincdir = $(includedir)/cfu
libcfuinc_HEADERS = cfu.h cfuhash.h cfutime.h cfustring.h cfulist.h \ libcfuinc_HEADERS = cfu.h cfuhash.h cfutime.h cfutimer.h cfustring.h \
cfuconf.h cfuopt.h cfulist.h cfuconf.h cfuopt.h
if USE_PTHREADS if USE_PTHREADS
libcfu_la_SOURCES += cfuthread_queue.c libcfu_la_SOURCES += cfuthread_queue.c

View File

@ -71,6 +71,14 @@ cfu_is_time(void *item) {
return 0; return 0;
} }
int
cfu_is_timer(void *item)
{
if (cfu_get_type(item) == libcfu_t_time)
return 1;
return 0;
}
extern int extern int
cfu_is_conf(void *item) { cfu_is_conf(void *item) {
if (cfu_get_type(item) == libcfu_t_conf) return 1; if (cfu_get_type(item) == libcfu_t_conf) return 1;

View File

@ -59,7 +59,7 @@ CFU_BEGIN_DECLS
#define LIBCFU_VERSION "0.04" #define LIBCFU_VERSION "0.04"
typedef enum { libcfu_t_none = 0, libcfu_t_hash_table, libcfu_t_list, libcfu_t_string, typedef enum { libcfu_t_none = 0, libcfu_t_hash_table, libcfu_t_list, libcfu_t_string,
libcfu_t_time, libcfu_t_conf } libcfu_type; libcfu_t_time, libcfu_t_timer, libcfu_t_conf } libcfu_type;
typedef struct libcfu_item libcfu_item_t; typedef struct libcfu_item libcfu_item_t;
@ -68,6 +68,7 @@ extern int cfu_is_hash(void *item);
extern int cfu_is_list(void *item); extern int cfu_is_list(void *item);
extern int cfu_is_string(void *item); extern int cfu_is_string(void *item);
extern int cfu_is_time(void *item); extern int cfu_is_time(void *item);
int cfu_is_timer(void *item);
extern int cfu_is_conf(void *item); extern int cfu_is_conf(void *item);
CFU_END_DECLS CFU_END_DECLS

101
src/cfutimer.c Normal file
View File

@ -0,0 +1,101 @@
/*
* cfutimer.c - This file is part of the libcfu library
*
* Copyright (c) Matthew Brush <mbrush@codebrainz.ca>.
* All rights reserved.
*
* This code is released under the BSD license, see COPYING file
* for full license text.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "cfu.h"
#include "cfutimer.h"
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <time.h>
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
/* For Windows, use a fairly accurate timer. This could probably be
* improved quite a bit (if it even works at all), by using performance
* counters stuff or thread cycle time from the API. Setting the afinity
* mask is probably also helpful. Note: not tested at all. */
#ifdef _WIN32
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# define TIMEVALUE_TYPE FILETIME
# define TIMEVALUE_NOW(tv) GetSystemTimeAsFileTime(&(tv))
# define TIMEVALUE_SEC(tv) ((double)(((uint64_t)(tv).dwHighDataTime << 32) + (tv).dwLowDateTime) * 10000000.0)
/* another option for windows, also untested
#define TIMEVALUE_TYPE LARGE_INTEGER
// future: set thread afinity mask
#define TIMEVALUE_NOW(tv) QueryPerformanceCounter(&(tv))
static INLINE double timevalue_sec_(TIMEVALUE_TYPE *tv) {
LARGE_INTEGER freq;
QueryPerformanceFrequency(&freq);
return (double) tv->QuadPart / (double) freq.QuadPart;
}
#define TIMEVALUE_SEC(tv) timevalue_sec_(&(tv))
*/
#else
/* For non-Windows systems check to see if the nano-second timer is
* available from POSIX. Note: must also be linked with -lrt.*/
# if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
# define TIMEVALUE_TYPE struct timespec
# define TIMEVALUE_NOW(tv) clock_gettime(CLOCK_MONOTONIC, &(tv))
# define TIMEVALUE_SEC(tv) ((double)(tv).tv_sec + ((double) (tv).tv_nsec / 1000000000.0))
/* For non-Windows systems that don't have the more accurate clock_gettime()
* then use the gettimeofday() function from POSIX if available. */
# elif defined(HAVE_GETTIMEOFDAY)
# define TIMEVALUE_TYPE struct timeval
# define TIMEVALUE_NOW(tv) gettimeofday(&(tv), NULL)
# define TIMEVALUE_SEC(tv) ((double)(tv).tv_sec + ((double) (tv).tv_usec / 1000000.0))
# else /* Fall-back to time() from stdlib */
# define TIMEVALUE_TYPE time_t
# define TIMEVALUE_NOW(tv) time(&(tv))
# define TIMEVALUE_SEC(tv) ((double)(tv))
# endif
#endif
struct cfutimer
{
libcfu_type type;
TIMEVALUE_TYPE t1;
TIMEVALUE_TYPE t2;
};
cfutimer_t *cfutimer_new(void)
{
cfutimer_t *timer = calloc(1, sizeof(cfutimer_t));
timer->type = libcfu_t_time;
return timer;
}
void cfutimer_start(cfutimer_t *timer)
{
memset(&(timer->t2), 0, sizeof(TIMEVALUE_TYPE));
TIMEVALUE_NOW(timer->t1);
}
void cfutimer_stop(cfutimer_t *timer)
{
TIMEVALUE_NOW(timer->t2);
}
double cfutimer_elapsed(cfutimer_t *timer)
{
return TIMEVALUE_SEC(timer->t2) - TIMEVALUE_SEC(timer->t1);
}
void cfutimer_free(cfutimer_t *timer)
{
free(timer);
}

37
src/cfutimer.h Normal file
View File

@ -0,0 +1,37 @@
/*
* cfutimer.h - This file is part of the libcfu library
*
* Copyright (c) Matthew Brush <mbrush@codebrainz.ca>.
* All rights reserved.
*
* This code is released under the BSD license, see COPYING file
* for full license text.
*/
#ifndef CFU_TIMER_H_
#define CFU_TIMER_H_
#include <cfu.h>
CFU_BEGIN_DECLS
typedef struct cfutimer cfutimer_t;
/* Return a new cfutimer structure. */
cfutimer_t *cfutimer_new(void);
/* Start the timer. */
void cfutimer_start(cfutimer_t *timer);
/* Stop the timer. */
void cfutimer_stop(cfutimer_t *timer);
/* Return the number of seconds elapsed as a double. */
double cfutimer_elapsed(cfutimer_t *timer);
/* Deallocate resources allocated for time. */
void cfutimer_free(cfutimer_t *timer);
CFU_END_DECLS
#endif /* CFU_TIMER_H_ */