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:
parent
d35b0f5b20
commit
b82a8f4ec6
@ -27,6 +27,12 @@ AC_FUNC_MALLOC
|
||||
AC_FUNC_MEMCMP
|
||||
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
|
||||
AC_CHECK_LIB([pthread],
|
||||
[pthread_create],
|
||||
|
@ -2,4 +2,4 @@ noinst_PROGRAMS = hash_usage large_hash strings conf_example \
|
||||
conf_example2 opt_example
|
||||
|
||||
AM_CFLAGS = -I$(top_srcdir)/src
|
||||
LDADD = $(top_builddir)/src/libcfu.la @PTHREAD_LIBS@
|
||||
LDADD = $(top_builddir)/src/libcfu.la @PTHREAD_LIBS@ @REALTIME_LIBS@
|
||||
|
@ -6,5 +6,5 @@ includedir=@includedir@
|
||||
Name: @PACKAGE_NAME@
|
||||
Description: Portable C data structure and utility library
|
||||
Version: @PACKAGE_VERSION@
|
||||
Libs.private: @PTHREAD_LIBS@
|
||||
Libs.private: @PTHREAD_LIBS@ @REALTIME_LIBS@
|
||||
Cflags: -I${includedir}/cfu
|
||||
|
@ -1,12 +1,13 @@
|
||||
lib_LTLIBRARIES = libcfu.la
|
||||
|
||||
libcfu_la_SOURCES = cfuhash.c cfutime.c cfustring.c cfulist.c \
|
||||
cfuconf.c cfu.c cfuopt.c snprintf.c
|
||||
libcfu_la_SOURCES = cfuhash.c cfutime.c cfutimer.c cfustring.c \
|
||||
cfulist.c cfuconf.c cfu.c cfuopt.c snprintf.c
|
||||
|
||||
libcfu_la_LIBADD = @PTHREAD_LIBS@ @REALTIME_LIBS@
|
||||
|
||||
libcfuincdir = $(includedir)/cfu
|
||||
libcfuinc_HEADERS = cfu.h cfuhash.h cfutime.h cfustring.h cfulist.h \
|
||||
cfuconf.h cfuopt.h
|
||||
libcfuinc_HEADERS = cfu.h cfuhash.h cfutime.h cfutimer.h cfustring.h \
|
||||
cfulist.h cfuconf.h cfuopt.h
|
||||
|
||||
if USE_PTHREADS
|
||||
libcfu_la_SOURCES += cfuthread_queue.c
|
||||
|
@ -71,6 +71,14 @@ cfu_is_time(void *item) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
cfu_is_timer(void *item)
|
||||
{
|
||||
if (cfu_get_type(item) == libcfu_t_time)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern int
|
||||
cfu_is_conf(void *item) {
|
||||
if (cfu_get_type(item) == libcfu_t_conf) return 1;
|
||||
|
@ -59,7 +59,7 @@ CFU_BEGIN_DECLS
|
||||
#define LIBCFU_VERSION "0.04"
|
||||
|
||||
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;
|
||||
|
||||
@ -68,6 +68,7 @@ extern int cfu_is_hash(void *item);
|
||||
extern int cfu_is_list(void *item);
|
||||
extern int cfu_is_string(void *item);
|
||||
extern int cfu_is_time(void *item);
|
||||
int cfu_is_timer(void *item);
|
||||
extern int cfu_is_conf(void *item);
|
||||
|
||||
CFU_END_DECLS
|
||||
|
101
src/cfutimer.c
Normal file
101
src/cfutimer.c
Normal 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
37
src/cfutimer.h
Normal 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_ */
|
Reference in New Issue
Block a user