Skip to content

Instantly share code, notes, and snippets.

@alexsr
Created June 18, 2020 06:53
Show Gist options
  • Save alexsr/2a6490ce6bdd9d1a82597af03d1b0e9d to your computer and use it in GitHub Desktop.
Save alexsr/2a6490ce6bdd9d1a82597af03d1b0e9d to your computer and use it in GitHub Desktop.
#include <functional>
#include <iostream>
#include <type_traits>
#include <optional>
#include <variant>
#include <chrono>
#include <memory>
//! Returns the time since epoch in ms
double get_current_time();
struct TimerBase
{
void start();
protected:
TimerBase(std::string const& name = "");
std::string name;
std::chrono::system_clock::time_point start_time;
};
struct SimpleTimer : public TimerBase
{
SimpleTimer(std::string const& name = "SimpleTimer");
std::int64_t get_time_passed_us();
void print_time_passed_us();
};
double get_current_time()
{
return std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::system_clock::now().time_since_epoch())
.count()
/ 1000.0;
}
//--------------------------------------------------------------------------------------------------
TimerBase::TimerBase(const std::string& name)
: name(name)
, start_time(std::chrono::system_clock::now())
{
}
void TimerBase::start() {
start_time = std::chrono::system_clock::now();
}
//--------------------------------------------------------------------------------------------------
SimpleTimer::SimpleTimer(std::string const& name)
: TimerBase(name)
{
}
//--------------------------------------------------------------------------------------------------
std::int64_t SimpleTimer::get_time_passed_us()
{
auto now = std::chrono::system_clock::now();
return std::chrono::duration_cast<std::chrono::microseconds>(now - start_time).count();
}
//--------------------------------------------------------------------------------------------------
void SimpleTimer::print_time_passed_us()
{
std::cout << name << ": " << get_time_passed_us() << " us" << std::endl;
}
struct ImuFrame {
float x= 2;
};
template<class> inline constexpr bool always_false_v = false;
template <typename R, typename ...Args>
struct Callback {
Callback() = default;
Callback(std::unique_ptr<Callback>&& ptr) noexcept {
*this = std::move(*ptr.get());
}
Callback(std::function<void()> const& f, std::unique_ptr<Callback> next = nullptr) :
f_(f), next_(std::move(next)) {}
Callback(std::function<R(Args&&...)> const& f, std::unique_ptr<Callback> next = nullptr) :
f_(f), next_(std::move(next)) {}
virtual void operator()(Args&&... args) {
if (f_.has_value()) {
std::visit([&](auto&& f) {
using T = std::decay_t<decltype(f)>;
if constexpr (std::is_same_v<T, std::function<void()>>)
f();
else if constexpr (std::is_same_v<T, std::function<R(Args&&...)>>)
f(std::forward<Args>(args)...);
else {
static_assert(always_false_v<T>, "non-exhaustive visitor!");
}
}, f_.value());
}
if (next_) {
(*next_)(std::forward<Args>(args)...);
}
};
void setNext(std::unique_ptr<Callback>&& next) {
next_ = std::move(next);
}
std::optional<std::variant<std::function<R(Args&&...)>, std::function<void()>>> f_;
std::unique_ptr<Callback> next_ = nullptr;
};
using IMUCallbackType = Callback<bool, int64_t, ImuFrame&>;
std::unique_ptr<IMUCallbackType> make_imu_processing_cb() {
return std::make_unique<IMUCallbackType>([](int64_t ts, ImuFrame& frame) {
std::cout << "x = " << frame.x << std::endl;
return true;
});
}
template <typename CbType>
std::unique_ptr<CbType> register_timer(SimpleTimer& timer, std::unique_ptr<CbType>&& cb) {
auto after = std::make_unique<CbType>([&timer] {
timer.print_time_passed_us();
});
cb->setNext(std::move(after));
auto before = std::make_unique<CbType>([&timer] {
timer.start();
std::cout << "Starting" << std::endl;
}, std::move(cb));
return before;
}
int main() {
SimpleTimer timer;
IMUCallbackType cb = register_timer(timer, make_imu_processing_cb());
ImuFrame imu;
cb(0, imu);
std::cout << "Henlo" << std::endl;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment