#include <chrono>
#include <cstdlib>
#include <functional>
#include <future>
#include <iostream>
#include <memory>
#include <string>
#include <thread>
#include <utility>
#include <vector>
class when {
public:
template <class Predicate, class Callable, typename... Args>
when(Predicate p, Callable c, Args... args)
{
std::thread thread(when_thread_entry<Predicate, Callable, Args...>(p, c, args...));
thread.detach();
}
private:
template <class Predicate, class Callable, typename... Args>
struct when_thread_entry {
when_thread_entry(Predicate p, Callable c, Args... args) : predicate(p), function(c), tuple(args...)
{
// Do nothing.
}
void operator()()
{
while (!(predicate()))
std::this_thread::yield();
call_function();
}
private:
template <int... Indices>
struct index {};
template <int N, int... Indices>
struct gen_seq : gen_seq<N - 1, N - 1, Indices...> {};
template <int... Indices>
struct gen_seq<0, Indices...> : index<Indices...> {};
Predicate predicate;
Callable function;
std::tuple<Args...> tuple;
template <int... Indices>
void call_function(index<Indices...>)
{
function(std::get<Indices>(tuple)...);
}
void call_function()
{
call_function(gen_seq<sizeof...(Args)>{});
}
};
};
struct timeout_predicate {
timeout_predicate(std::time_t duration) : end(curtime() + duration)
{
// Do nothing.
}
bool operator()()
{
return (curtime() >= end);
}
private:
std::time_t end;
std::time_t curtime()
{
return std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
}
};
class after : public when {
public:
template <class Callable, typename... Args>
after(std::time_t timeout, Callable c, Args... args) : when(timeout_predicate(timeout), c, args...)
{
// Do nothing.
}
};
struct string_printer {
string_printer(std::ostream& stream) : m_stream(stream)
{
// Do nothing.
}
void operator()(const std::string& string)
{
m_stream << string;
}
private:
std::ostream& m_stream;
};
struct stream_flusher {
stream_flusher(std::ostream& stream) : m_stream(stream)
{
// Do nothing.
}
void operator()()
{
m_stream << std::flush;
}
private:
std::ostream& m_stream;
};
struct program_exiter {
void operator()(int exit_code = EXIT_SUCCESS)
{
std::exit(exit_code);
}
};
int main()
{
string_printer printer(std::cout);
stream_flusher flusher(std::cout);
program_exiter exiter;
after( 9, flusher);
after( 7, printer, "hello, world\n");
after( 3, printer, "Message: ");
after( 5, flusher);
after(10, exiter, EXIT_SUCCESS);
while (true)
;
}
I2luY2x1ZGUgPGNocm9ubz4KI2luY2x1ZGUgPGNzdGRsaWI+CiNpbmNsdWRlIDxmdW5jdGlvbmFsPgojaW5jbHVkZSA8ZnV0dXJlPgojaW5jbHVkZSA8aW9zdHJlYW0+CiNpbmNsdWRlIDxtZW1vcnk+CiNpbmNsdWRlIDxzdHJpbmc+CiNpbmNsdWRlIDx0aHJlYWQ+CiNpbmNsdWRlIDx1dGlsaXR5PgojaW5jbHVkZSA8dmVjdG9yPgoKCmNsYXNzIHdoZW4gewpwdWJsaWM6CiAgICB0ZW1wbGF0ZSA8Y2xhc3MgUHJlZGljYXRlLCBjbGFzcyBDYWxsYWJsZSwgdHlwZW5hbWUuLi4gQXJncz4KICAgIHdoZW4oUHJlZGljYXRlIHAsIENhbGxhYmxlIGMsIEFyZ3MuLi4gYXJncykKICAgIHsKICAgICAgICBzdGQ6OnRocmVhZCB0aHJlYWQod2hlbl90aHJlYWRfZW50cnk8UHJlZGljYXRlLCBDYWxsYWJsZSwgQXJncy4uLj4ocCwgYywgYXJncy4uLikpOwogICAgICAgIHRocmVhZC5kZXRhY2goKTsKICAgIH0KcHJpdmF0ZToKICAgIHRlbXBsYXRlIDxjbGFzcyBQcmVkaWNhdGUsIGNsYXNzIENhbGxhYmxlLCB0eXBlbmFtZS4uLiBBcmdzPgogICAgc3RydWN0IHdoZW5fdGhyZWFkX2VudHJ5IHsKICAgICAgICB3aGVuX3RocmVhZF9lbnRyeShQcmVkaWNhdGUgcCwgQ2FsbGFibGUgYywgQXJncy4uLiBhcmdzKSA6IHByZWRpY2F0ZShwKSwgZnVuY3Rpb24oYyksIHR1cGxlKGFyZ3MuLi4pCiAgICAgICAgewogICAgICAgICAgICAvLyBEbyBub3RoaW5nLgogICAgICAgIH0KICAgICAgICAKICAgICAgICB2b2lkIG9wZXJhdG9yKCkoKQogICAgICAgIHsKICAgICAgICAgICAgd2hpbGUgKCEocHJlZGljYXRlKCkpKQogICAgICAgICAgICAgICAgc3RkOjp0aGlzX3RocmVhZDo6eWllbGQoKTsKICAgICAgICAgICAgY2FsbF9mdW5jdGlvbigpOwogICAgICAgIH0KICAgIHByaXZhdGU6CiAgICAgICAgdGVtcGxhdGUgPGludC4uLiBJbmRpY2VzPgogICAgICAgIHN0cnVjdCBpbmRleCB7fTsKICAgICAgICB0ZW1wbGF0ZSA8aW50IE4sIGludC4uLiBJbmRpY2VzPgogICAgICAgIHN0cnVjdCBnZW5fc2VxIDogZ2VuX3NlcTxOIC0gMSwgTiAtIDEsIEluZGljZXMuLi4+IHt9OwogICAgICAgIHRlbXBsYXRlIDxpbnQuLi4gSW5kaWNlcz4KICAgICAgICBzdHJ1Y3QgZ2VuX3NlcTwwLCBJbmRpY2VzLi4uPiA6IGluZGV4PEluZGljZXMuLi4+IHt9OwoKICAgICAgICBQcmVkaWNhdGUgcHJlZGljYXRlOwogICAgICAgIENhbGxhYmxlIGZ1bmN0aW9uOwogICAgICAgIHN0ZDo6dHVwbGU8QXJncy4uLj4gdHVwbGU7CgogICAgICAgIHRlbXBsYXRlIDxpbnQuLi4gSW5kaWNlcz4KICAgICAgICB2b2lkIGNhbGxfZnVuY3Rpb24oaW5kZXg8SW5kaWNlcy4uLj4pCiAgICAgICAgewogICAgICAgICAgICBmdW5jdGlvbihzdGQ6OmdldDxJbmRpY2VzPih0dXBsZSkuLi4pOwogICAgICAgIH0KCiAgICAgICAgdm9pZCBjYWxsX2Z1bmN0aW9uKCkKICAgICAgICB7CiAgICAgICAgICAgIGNhbGxfZnVuY3Rpb24oZ2VuX3NlcTxzaXplb2YuLi4oQXJncyk+e30pOwogICAgICAgIH0KICAgIH07Cn07CgpzdHJ1Y3QgdGltZW91dF9wcmVkaWNhdGUgewogICAgdGltZW91dF9wcmVkaWNhdGUoc3RkOjp0aW1lX3QgZHVyYXRpb24pIDogZW5kKGN1cnRpbWUoKSArIGR1cmF0aW9uKQogICAgewogICAgICAgIC8vIERvIG5vdGhpbmcuCiAgICB9CgogICAgYm9vbCBvcGVyYXRvcigpKCkKICAgIHsKICAgICAgICByZXR1cm4gKGN1cnRpbWUoKSA+PSBlbmQpOwogICAgfQpwcml2YXRlOgogICAgc3RkOjp0aW1lX3QgZW5kOwoKICAgIHN0ZDo6dGltZV90IGN1cnRpbWUoKQogICAgewogICAgICAgIHJldHVybiBzdGQ6OmNocm9ubzo6c3lzdGVtX2Nsb2NrOjp0b190aW1lX3Qoc3RkOjpjaHJvbm86OnN5c3RlbV9jbG9jazo6bm93KCkpOwogICAgfQp9OwoKY2xhc3MgYWZ0ZXIgOiBwdWJsaWMgd2hlbiB7CnB1YmxpYzoKICAgIHRlbXBsYXRlIDxjbGFzcyBDYWxsYWJsZSwgdHlwZW5hbWUuLi4gQXJncz4KICAgIGFmdGVyKHN0ZDo6dGltZV90IHRpbWVvdXQsIENhbGxhYmxlIGMsIEFyZ3MuLi4gYXJncykgOiB3aGVuKHRpbWVvdXRfcHJlZGljYXRlKHRpbWVvdXQpLCBjLCBhcmdzLi4uKQogICAgewogICAgICAgIC8vIERvIG5vdGhpbmcuCiAgICB9Cn07CgpzdHJ1Y3Qgc3RyaW5nX3ByaW50ZXIgewogICAgc3RyaW5nX3ByaW50ZXIoc3RkOjpvc3RyZWFtJiBzdHJlYW0pIDogbV9zdHJlYW0oc3RyZWFtKQogICAgewogICAgICAgIC8vIERvIG5vdGhpbmcuCiAgICB9CgogICAgdm9pZCBvcGVyYXRvcigpKGNvbnN0IHN0ZDo6c3RyaW5nJiBzdHJpbmcpCiAgICB7CiAgICAgICAgbV9zdHJlYW0gPDwgc3RyaW5nOwogICAgfQpwcml2YXRlOgogICAgc3RkOjpvc3RyZWFtJiBtX3N0cmVhbTsKfTsKCnN0cnVjdCBzdHJlYW1fZmx1c2hlciB7CiAgICBzdHJlYW1fZmx1c2hlcihzdGQ6Om9zdHJlYW0mIHN0cmVhbSkgOiBtX3N0cmVhbShzdHJlYW0pCiAgICB7CiAgICAgICAgLy8gRG8gbm90aGluZy4KICAgIH0KCiAgICB2b2lkIG9wZXJhdG9yKCkoKQogICAgewogICAgICAgIG1fc3RyZWFtIDw8IHN0ZDo6Zmx1c2g7CiAgICB9CnByaXZhdGU6CiAgICBzdGQ6Om9zdHJlYW0mIG1fc3RyZWFtOwp9OwoKc3RydWN0IHByb2dyYW1fZXhpdGVyIHsKICAgIHZvaWQgb3BlcmF0b3IoKShpbnQgZXhpdF9jb2RlID0gRVhJVF9TVUNDRVNTKQogICAgewogICAgICAgIHN0ZDo6ZXhpdChleGl0X2NvZGUpOwogICAgfQp9OwoKaW50IG1haW4oKQp7CiAgICBzdHJpbmdfcHJpbnRlciBwcmludGVyKHN0ZDo6Y291dCk7CiAgICBzdHJlYW1fZmx1c2hlciBmbHVzaGVyKHN0ZDo6Y291dCk7CiAgICBwcm9ncmFtX2V4aXRlciBleGl0ZXI7CiAgICBhZnRlciggOSwgZmx1c2hlcik7CiAgICBhZnRlciggNywgcHJpbnRlciwgImhlbGxvLCB3b3JsZFxuIik7CiAgICBhZnRlciggMywgcHJpbnRlciwgIk1lc3NhZ2U6ICIpOwogICAgYWZ0ZXIoIDUsIGZsdXNoZXIpOwogICAgYWZ0ZXIoMTAsIGV4aXRlciwgRVhJVF9TVUNDRVNTKTsKICAgIHdoaWxlICh0cnVlKQogICAgICAgIDsKfQ==