# include "bits.h"
#endif
+#ifndef MLIB_DSTR_H
+# include "dstr.h"
+#endif
+
/*----- Data structures ---------------------------------------------------*/
struct bench_time {
struct bench_timer { const struct bench_timerops *ops; };
struct bench_timerops {
+ void (*describe)(struct bench_timer */*bt*/, dstr */*d*/);
+ /* Write a description of the timer to @d@. */
+
void (*now)(struct bench_timer */*bt*/, struct bench_time */*t_out*/);
/* Fill in @*t_out@ with the current time. v*/
struct bench_timer *tm; /* a timer */
double target_s; /* target time to run benchmarks */
unsigned f; /* calibration flags (@BTF_...@) */
+#define BTF_CLB 0x0100 /* tried calibrating */
struct { double m, c; } clk, cy; /* calculated overheads */
};
/* --- @bench_createtimer@ --- *
*
- * Arguments: ---
+ * Arguments: @const char *config@ = user-supplied configuration string
*
- * Returns: A freshly constructed standard timer object.
+ * Returns: A freshly constructed standard timer object, or null on
+ * failure.
*
* Use: Allocate a timer. Dispose of it by calling
* @tm->ops->destroy(tm)@ when you're done.
+ *
+ * Applications should not set configuration strings except as
+ * established by user action, e.g., from a command-line option,
+ * environment variable, or configuration file.
*/
-extern struct bench_timer *bench_createtimer(void);
+extern struct bench_timer *bench_createtimer(const char *config);
/* --- @bench_init@ --- *
*
* Arguments: @struct bench_state *b@ = bench state to initialize
- * @struct bench_timer *tm@ = timer to attach
+ * @struct bench_timer *tm@ = timer to attach, or null
*
- * Returns: ---
+ * Returns: Zero on success, %$-1$% on failure.
+ *
+ * Use: Initialize the benchmark state. On success, the timer state
+ * still needs to be calibrated (use @bench_calibrate@) before
+ * it can be used, but this will be done automatically by
+ * @bench_measure@ if it's not done by hand earlier. The timer
+ * is now owned by the benchmark state and will be destroyed by
+ * @bench_destroy@.
*
- * Use: Initialize the benchmark state. It still needs to be
- * calibrated (use @bench_calibrate@) before it can be used, but
- * this will be done automatically by @bench_measure@ if it's
- * not done by hand earlier. The timer is now owned by the
- * benchmark state and will be destroyed by @bench_destroy@.
+ * The only reason for failure is if @tm@ was null on entry,
+ * and automatic construction of a timer failed. The state is
+ * safe to discard, but calling @bench_destroy@ is safe too.
*/
-extern void bench_init(struct bench_state */*b*/,
- struct bench_timer */*tm*/);
+extern int bench_init(struct bench_state */*b*/, struct bench_timer */*tm*/);
/* --- @bench_destroy@ --- *
*
*
* Arguments: @struct bench_state *b@ = bench state
*
- * Returns: Zero on success, @-1@ if calibration failed.
+ * Returns: Zero on success, %$-1$% if calibration failed.
*
* Use: Calibrate the benchmark state, so that it can be used to
* measure performance reasonably accurately.
* @double base@ = number of internal units per call
* @bench_fn *fn@, @void *ctx@ = benchmark function to run
*
- * Returns: Zero on success, @-1@ if timing failed.
+ * Returns: Zero on success, %$-1$% if timing failed.
*
* Use: Measure a function. The function @fn@ is called adaptively
* with an iteration count @n@ set so as to run for