#ifndef THROUGHPUT_IF_H
#define THROUGHPUT_IF_H

typedef void (*timer_cb)(void);
typedef unsigned long long (*timer_value_cb)(void);
typedef unsigned long (*count_cb)(void);

typedef struct {
	timer_cb start;
	timer_cb stop;
	timer_cb reset;
	timer_value_cb value;
} timer_callback;

typedef struct {
	double throughput;
	double delta_time;
} throughput_stat;

/**
 * NOTE: Getting the elapsed time in implementation requires Linux, since
 * the baremetal OSes do not currently have the generic timers
 * configured.
 */
class throughput_monitor {
private:
	static constexpr unsigned long long FREQUENCY =
#ifdef SPACE_IMPLEMENTATION
		1000;
#else
		1000000000000;
#endif

public:
#ifdef SPACE_IMPLEMENTATION
	throughput_monitor();
#else
	throughput_monitor(timer_value_cb timer_value);
#endif
	// Should not define a destructor, not even in the header,
	// otherwise, at least in monitoring, libc++ would
	// add a bunch of code to handle a potential exception, which
	// makes the executable size greater than the size of
	// the microblaze's RAM.

	throughput_stat get_throughput();
	void reset();

private:
	timer_callback m_timer_callbacks;
	count_cb m_count;
	unsigned long m_last_count = 0;
	unsigned long long m_value = 0;
	unsigned long long m_access_delay = 0;
};

#endif
