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_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],
|
||||||
|
@ -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@
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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
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