Created
June 18, 2020 06:53
-
-
Save alexsr/2a6490ce6bdd9d1a82597af03d1b0e9d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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